about summary refs log tree commit diff
path: root/converter/other/jpeg2000
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/jpeg2000')
-rw-r--r--converter/other/jpeg2000/Makefile6
-rw-r--r--converter/other/jpeg2000/jpeg2ktopam.c34
-rw-r--r--converter/other/jpeg2000/libjasper/base/jas_image.c74
-rw-r--r--converter/other/jpeg2000/libjasper/base/jas_stream.c31
-rw-r--r--converter/other/jpeg2000/libjasper/include/jasper/jas_image.h27
-rw-r--r--converter/other/jpeg2000/libjasper/jp2/jp2_dec.c93
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_dec.c1085
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_dec.h2
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_enc.c1377
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_enc.h2
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_math.c2
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_mqenc.c31
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.c1566
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.h14
-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/libjasper_compat.c26
-rw-r--r--converter/other/jpeg2000/libjasper_compat.h35
-rw-r--r--converter/other/jpeg2000/pamtojpeg2k.c29
19 files changed, 2545 insertions, 2123 deletions
diff --git a/converter/other/jpeg2000/Makefile b/converter/other/jpeg2000/Makefile
index 6e5af8e7..9c8729ac 100644
--- a/converter/other/jpeg2000/Makefile
+++ b/converter/other/jpeg2000/Makefile
@@ -46,8 +46,8 @@ endif
 
 BINARIES = $(PORTBINARIES)
 
-OBJECTS = $(BINARIES:%=%.o)
-MERGE_OBJECTS = $(BINARIES:%=%.o2) 
+OBJECTS = $(BINARIES:%=%.o) libjasper_compat.o
+MERGE_OBJECTS = $(BINARIES:%=%.o2) libjasper_compat.o2
 ifeq ($(JASPERLIB),$(INTERNAL_JASPERLIB))
   # MERGE_OBJECTS contains relative paths, so $(INTERNAL_JASPERLIB) had better
   # be relative to the current directory.
@@ -63,7 +63,7 @@ include $(SRCDIR)/common.mk
 
 LIBOPTS = $(shell $(LIBOPT) $(JASPERLIB_USE))
 
-$(BINARIES): %: %.o $(JASPERLIB_DEP) $(LIBOPT)
+$(BINARIES): %: %.o libjasper_compat.o $(JASPERLIB_DEP) $(LIBOPT)
 $(BINARIES): LDFLAGS_TARGET = $(LIBOPTS) $(JASPERDEPLIBS)
 
 $(INTERNAL_JASPERLIB): $(BUILDDIR)/$(SUBDIR)/libjasper FORCE
diff --git a/converter/other/jpeg2000/jpeg2ktopam.c b/converter/other/jpeg2000/jpeg2ktopam.c
index b507f56e..bda0de2e 100644
--- a/converter/other/jpeg2000/jpeg2ktopam.c
+++ b/converter/other/jpeg2000/jpeg2ktopam.c
@@ -29,11 +29,9 @@
 
 #include "libjasper_compat.h"
 
-enum compmode {COMPMODE_INTEGER, COMPMODE_REAL};
 
-enum progression {PROG_LRCP, PROG_RLCP, PROG_RPCL, PROG_PCRL, PROG_CPRL};
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
@@ -44,15 +42,15 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine(int argc, char ** argv,
-                 struct cmdlineInfo * const cmdlineP) {
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that many of the strings that this function returns in the
    *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!
 -----------------------------------------------------------------------------*/
-    optEntry *option_def;
+    optEntry * option_def;
     optStruct3 opt;
 
     unsigned int debuglevelSpec;
@@ -71,7 +69,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char**)argv, opt, sizeof(opt), 0);
 
     if (!debuglevelSpec)
         cmdlineP->debuglevel = 0;
@@ -84,6 +82,7 @@ parseCommandLine(int argc, char ** argv,
         pm_error("Too many arguments.  The only argument accepted\n"
                  "is the input file specification");
 
+    free(option_def);
 }
 
 
@@ -114,9 +113,11 @@ static void
 readJ2k(const char *   const inputFilename,
         jas_image_t ** const jasperPP) {
 
+    const char * const options = "";
+
     jas_image_t * jasperP;
     jas_stream_t * instreamP;
-    const char * options;
+    const char * error;
 
     if (streq(inputFilename, "-")) {
         /* The input image is to be read from standard input. */
@@ -131,13 +132,10 @@ readJ2k(const char *   const inputFilename,
 
     validateJ2k(instreamP);
 
-    options = "";
-
-    jasperP = jas_image_decode(instreamP, jas_image_getfmt(instreamP),
-                               (char*)options);
-    if (jasperP == NULL)
-        pm_error("Unable to interpret JPEG-2000 input.  "
-                 "The Jasper library jas_image_decode() subroutine failed.");
+    pmjas_image_decode(instreamP, jas_image_getfmt(instreamP), options,
+                       &jasperP, &error);
+    if (error)
+        pm_error("Unable to interpret JPEG-2000 input.  %s", error);
 
     jas_stream_close(instreamP);
 
@@ -483,9 +481,9 @@ convertToPamPnm(struct pam *  const outpamP,
 
 
 int
-main(int argc, char **argv)
+main(int argc, const char **argv)
 {
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     struct pam outpam;
     int * jasperCmpt;  /* malloc'ed */
        /* jaspercmpt[P] is the component number for use with the
@@ -493,7 +491,7 @@ main(int argc, char **argv)
        */
     jas_image_t * jasperP;
 
-    pnm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
diff --git a/converter/other/jpeg2000/libjasper/base/jas_image.c b/converter/other/jpeg2000/libjasper/base/jas_image.c
index 5c2822be..c6f984c1 100644
--- a/converter/other/jpeg2000/libjasper/base/jas_image.c
+++ b/converter/other/jpeg2000/libjasper/base/jas_image.c
@@ -126,6 +126,8 @@
 #include <assert.h>
 #include <ctype.h>
 
+#include "netpbm/nstring.h"
+
 #include "jasper/jas_math.h"
 #include "jasper/jas_image.h"
 #include "jasper/jas_malloc.h"
@@ -379,22 +381,47 @@ static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt)
 * Load and save operations.
 \*****************************************************************************/
 
-jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, char *optstr)
-{
+void
+pmjas_image_decode(jas_stream_t * const in,
+				   int            const fmtArg,
+				   const char *   const optstr,
+				   jas_image_t ** const imagePP,
+				   const char **  const errorP) {
+/*----------------------------------------------------------------------------
+  Create an image from a stream in some specified format
+-----------------------------------------------------------------------------*/
 	jas_image_fmtinfo_t *fmtinfo;
+	int fmt;
 
 	/* If possible, try to determine the format of the input data. */
-	if (fmt < 0) {
+	if (fmtArg < 0) {
 		if ((fmt = jas_image_getfmt(in)) < 0) {
-			return 0;
+			pm_asprintf(errorP, "jas_image_getfmt failed");
+			return;
 		}
-	}
+	} else
+		fmt = fmtArg;
+
 	if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) {
-		return 0;
+		pm_asprintf(errorP, "jas_image_lookupfmtbyid of format %d failed",
+					fmt);
+		return;
+	}
+	{
+		const char * error;
+
+		(*fmtinfo->ops.decode)(in, optstr, imagePP, &error);
+		if (error) {
+			pm_asprintf(errorP, "decoder failed.  %s", error);
+			pm_strfree(error);
+		} else {
+			*errorP = NULL;
+		}
 	}
-	return (fmtinfo->ops.decode) ? (*fmtinfo->ops.decode)(in, optstr) : 0;
 }
 
+
+
 int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, char *optstr)
 {
 	jas_image_fmtinfo_t *fmtinfo;
@@ -648,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? */
@@ -659,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/base/jas_stream.c b/converter/other/jpeg2000/libjasper/base/jas_stream.c
index 24f835ed..a4b3a27c 100644
--- a/converter/other/jpeg2000/libjasper/base/jas_stream.c
+++ b/converter/other/jpeg2000/libjasper/base/jas_stream.c
@@ -6,14 +6,14 @@
  */
 
 /* __START_OF_JASPER_LICENSE__
- * 
+ *
  * JasPer Software License
- * 
+ *
  * IMAGE POWER JPEG-2000 PUBLIC LICENSE
  * ************************************
- * 
+ *
  * GRANT:
- * 
+ *
  * Permission is hereby granted, free of charge, to any person (the "User")
  * obtaining a copy of this software and associated documentation, to deal
  * in the JasPer Software without restriction, including without limitation
@@ -21,22 +21,22 @@
  * and/or sell copies of the JasPer Software (in source and binary forms),
  * and to permit persons to whom the JasPer Software is furnished to do so,
  * provided further that the License Conditions below are met.
- * 
+ *
  * License Conditions
  * ******************
- * 
+ *
  * A.  Redistributions of source code must retain the above copyright notice,
  * and this list of conditions, and the following disclaimer.
- * 
+ *
  * B.  Redistributions in binary form must reproduce the above copyright
  * notice, and this list of conditions, and the following disclaimer in
  * the documentation and/or other materials provided with the distribution.
- * 
+ *
  * C.  Neither the name of Image Power, Inc. nor any other contributor
  * (including, but not limited to, the University of British Columbia and
  * Michael David Adams) may be used to endorse or promote products derived
  * from this software without specific prior written permission.
- * 
+ *
  * D.  User agrees that it shall not commence any action against Image Power,
  * Inc., the University of British Columbia, Michael David Adams, or any
  * other contributors (collectively "Licensors") for infringement of any
@@ -56,17 +56,17 @@
  * trade dress, or service mark rights); and (v) divisions, continuations,
  * renewals, reissues and extensions of the foregoing (as and to the extent
  * applicable) now existing, hereafter filed, issued or acquired.
- * 
+ *
  * E.  If User commences an infringement action against any Licensor(s) then
  * such Licensor(s) shall have the right to terminate User's license and
  * all sublicenses that have been granted hereunder by User to other parties.
- * 
+ *
  * F.  This software is for use only in hardware or software products that
  * are compliant with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1).  No license
  * or right to this Software is granted for products that do not comply
  * with ISO/IEC 15444-1.  The JPEG-2000 Part 1 standard can be purchased
  * from the ISO.
- * 
+ *
  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
  * NO USE OF THE JASPER SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  * THIS DISCLAIMER.  THE JASPER SOFTWARE IS PROVIDED BY THE LICENSORS AND
@@ -106,10 +106,11 @@
  * TECHNOLOGY OR PRODUCTS FOR HIGH RISK ACTIVITIES AND WILL ENSURE THAT ITS
  * CUSTOMERS AND END-USERS OF ITS PRODUCTS ARE PROVIDED WITH A COPY OF THE
  * NOTICE SPECIFIED IN THIS SECTION.
- * 
+ *
  * __END_OF_JASPER_LICENSE__
  */
 
+#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */
 #define _SVID_SOURCE
     /* Make sure P_tmpdir is defined in GNU libc 2.0.7 (_XOPEN_SOURCE 500
        does it in other libc's).  pm_config.h defines TMPDIR as P_tmpdir
@@ -276,7 +277,7 @@ jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
 		obj->len_ = 0;
 	}
 	obj->pos_ = 0;
-	
+
 	return stream;
 }
 
@@ -409,7 +410,7 @@ jas_stream_t *jas_stream_tmpfile()
         */
         jmp_buf jmpbuf;
         int rc;
-        
+
         rc = setjmp(jmpbuf);
         if (rc == 0) {
             pm_setjmpbuf(&jmpbuf);
diff --git a/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h b/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h
index 6e914efd..20170986 100644
--- a/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h
+++ b/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h
@@ -300,7 +300,10 @@ typedef struct {
 
 typedef struct {
 
-	jas_image_t *(*decode)(jas_stream_t *in, char *opts);
+	void (*decode)(jas_stream_t * const in,
+				   const char *   const opts,
+				   jas_image_t ** const imagePP,
+				   const char **  const errorP);
 	/* Decode image data from a stream. */
 
 	int (*encode)(jas_image_t *image, jas_stream_t *out, char *opts);
@@ -442,8 +445,14 @@ void jas_image_destroy(jas_image_t *image);
   any compression. */
 uint_fast32_t jas_image_rawsize(jas_image_t *image);
 
-/* Create an image from a stream in some specified format. */
-jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, char *optstr);
+#define JAS_HAVE_PMJAS_IMAGE_DECODE
+
+void
+pmjas_image_decode(jas_stream_t * const in,
+				   int            const fmt,
+				   const char *   const optstr,
+				   jas_image_t ** const imagePP,
+				   const char **  const errorP);
 
 /* Write an image to a stream in a specified format. */
 int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt,
@@ -567,14 +576,22 @@ int bmp_validate(jas_stream_t *in);
 
 #if !defined(EXCLUDE_JP2_CAPABILITY)
 /* Format-dependent operations for JP2 capability. */
-jas_image_t *jp2_decode(jas_stream_t *in, char *optstr);
+void
+jp2_decode(jas_stream_t * const in,
+		   const char *   const optstr,
+		   jas_image_t ** const imagePP,
+		   const char **  const errorP);
 int jp2_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int jp2_validate(jas_stream_t *in);
 #endif
 
 #if !defined(EXCLUDE_JPC_CAPABILITY)
 /* Format-dependent operations for JPEG-2000 code stream capability. */
-jas_image_t *jpc_decode(jas_stream_t *in, char *optstr);
+void
+jpc_decode(jas_stream_t * const in,
+           const char *   const optstr,
+           jas_image_t ** const imagePP,
+           const char **  const errorP);
 int jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int jpc_validate(jas_stream_t *in);
 #endif
diff --git a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c
index 4036f0f2..e8d71b0a 100644
--- a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c
+++ b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c
@@ -117,6 +117,8 @@
 #include "jasper/jas_malloc.h"
 #include "jasper/jas_version.h"
 
+#include "netpbm/nstring.h"
+
 #include "jp2_cod.h"
 #include "jp2_dec.h"
 
@@ -271,8 +273,11 @@ fromiccpcs(int cs) {
 
 
 
-jas_image_t *
-jp2_decode(jas_stream_t *in, char *optstr) {
+void
+jp2_decode(jas_stream_t * const in,
+           const char *   const optstr,
+           jas_image_t ** const imagePP,
+           const char **  const errorP) {
 
     jp2_box_t *box;
     int found;
@@ -295,32 +300,34 @@ jp2_decode(jas_stream_t *in, char *optstr) {
     image = 0;
 
     if (!(dec = jp2_dec_create())) {
-        goto error;
+        pm_asprintf(errorP, "jp2_dec_create failed");
+        goto cleanup;
     }
 
     /* Get the first box.  This should be a JP box. */
     if (!(box = jp2_box_get(in))) {
-        jas_eprintf("error: cannot get box\n");
-        goto error;
+        pm_asprintf(errorP, "cannot get box");
+        goto cleanup;
     }
     if (box->type != JP2_BOX_JP) {
-        jas_eprintf("error: expecting signature box\n");
-        goto error;
+        pm_asprintf(errorP, "expecting signature box");
+        goto cleanup;
     }
     if (box->data.jp.magic != JP2_JP_MAGIC) {
-        jas_eprintf("incorrect magic number\n");
-        goto error;
+        pm_asprintf(errorP, "incorrect magic number");
+        goto cleanup;
     }
     jp2_box_destroy(box);
     box = 0;
 
     /* Get the second box.  This should be a FTYP box. */
     if (!(box = jp2_box_get(in))) {
-        goto error;
+        pm_asprintf(errorP, "cannot get second box");
+        goto cleanup;
     }
     if (box->type != JP2_BOX_FTYP) {
-        jas_eprintf("expecting file type box\n");
-        goto error;
+        pm_asprintf(errorP, "expecting file type box");
+        goto cleanup;
     }
     jp2_box_destroy(box);
     box = 0;
@@ -329,7 +336,7 @@ jp2_decode(jas_stream_t *in, char *optstr) {
     found = 0;
     while ((box = jp2_box_get(in))) {
         if (jas_getdbglevel() >= 1) {
-            fprintf(stderr, "box type %s\n", box->info->name);
+            jas_eprintf("box type '%s'\n", box->info->name);
         }
         switch (box->type) {
         case JP2_BOX_JP2C:
@@ -382,19 +389,24 @@ jp2_decode(jas_stream_t *in, char *optstr) {
     }
 
     if (!found) {
-        jas_eprintf("error: no code stream found\n");
-        goto error;
+        pm_asprintf(errorP, "no code stream found");
+        goto cleanup;
     }
 
-    if (!(dec->image = jpc_decode(in, optstr))) {
-        jas_eprintf("error: cannot decode code stream\n");
-        goto error;
+    {
+        const char * decodeError;
+        jpc_decode(in, optstr, &dec->image, &decodeError);
+        if (decodeError) {
+            pm_asprintf(errorP, "cannot decode code stream.  %s", decodeError);
+            pm_strfree(decodeError);
+            goto cleanup;
+        }
     }
 
     /* An IHDR box must be present. */
     if (!dec->ihdr) {
-        jas_eprintf("error: missing IHDR box\n");
-        goto error;
+        pm_asprintf(errorP, "missing IHDR box");
+        goto cleanup;
     }
 
     /* Does the number of components indicated in the IHDR box match
@@ -405,8 +417,8 @@ jp2_decode(jas_stream_t *in, char *optstr) {
 
     /* At least one component must be present. */
     if (!jas_image_numcmpts(dec->image)) {
-        jas_eprintf("error: no components\n");
-        goto error;
+        pm_asprintf(errorP, "no components");
+        goto cleanup;
     }
 
     /* Determine if all components have the same data type. */
@@ -428,15 +440,15 @@ jp2_decode(jas_stream_t *in, char *optstr) {
 
     /* Can we handle the compression type? */
     if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) {
-        jas_eprintf("error: not capable of this compression type\n");
-        goto error;
+        pm_asprintf(errorP, "not capable of this compression type");
+        goto cleanup;
     }
 
     if (dec->bpcc) {
         /* Is the number of components indicated in the BPCC box
           consistent with the code stream data? */
         if (dec->bpcc->data.bpcc.numcmpts != jas_image_numcmpts(
-          dec->image)) {
+                dec->image)) {
             jas_eprintf("warning: number of components mismatch\n");
         }
         /* Is the component data type information indicated in the BPCC
@@ -455,8 +467,8 @@ jp2_decode(jas_stream_t *in, char *optstr) {
 
     /* A COLR box must be present. */
     if (!dec->colr) {
-        jas_eprintf("error: no COLR box\n");
-        goto error;
+        pm_asprintf(errorP, "no COLR box");
+        goto cleanup;
     }
 
     switch (dec->colr->data.colr.method) {
@@ -502,14 +514,14 @@ jp2_decode(jas_stream_t *in, char *optstr) {
             /* Is the component number reasonable? */
             if (dec->cmap->data.cmap.ents[i].cmptno >=
                 jas_image_numcmpts(dec->image)) {
-                jas_eprintf("error: invalid component number in CMAP box\n");
-                goto error;
+                pm_asprintf(errorP, "invalid component number in CMAP box");
+                goto cleanup;
             }
             /* Is the LUT index reasonable? */
             if (dec->cmap->data.cmap.ents[i].pcol >=
                 dec->pclr->data.pclr.numchans) {
-                jas_eprintf("error: invalid CMAP LUT index\n");
-                goto error;
+                pm_asprintf(errorP, "invalid CMAP LUT index");
+                goto cleanup;
             }
         }
     }
@@ -517,8 +529,8 @@ jp2_decode(jas_stream_t *in, char *optstr) {
     /* Allocate space for the channel-number to component-number LUT. */
     dec->chantocmptlut = jas_malloc(dec->numchans * sizeof(uint_fast16_t));
     if (!dec->chantocmptlut) {
-        jas_eprintf("error: no memory\n");
-        goto error;
+        pm_asprintf(errorP, "no memory");
+        goto cleanup;
     }
 
     if (!dec->cmap) {
@@ -564,8 +576,8 @@ jp2_decode(jas_stream_t *in, char *optstr) {
                 }
 #endif
             } else {
-                jas_eprintf("error: invalid MTYP in CMAP box\n");
-                goto error;
+                pm_asprintf(errorP, "invalid MTYP in CMAP box");
+                goto cleanup;
             }
         }
     }
@@ -604,8 +616,8 @@ jp2_decode(jas_stream_t *in, char *optstr) {
 
     /* Ensure that some components survived. */
     if (!jas_image_numcmpts(dec->image)) {
-        jas_eprintf("error: no components\n");
-        goto error;
+        pm_asprintf(errorP, "no components");
+        goto cleanup;
     }
 
     /* Prevent the image from being destroyed later. */
@@ -614,16 +626,17 @@ jp2_decode(jas_stream_t *in, char *optstr) {
 
     jp2_dec_destroy(dec);
 
-    return image;
+    *imagePP = image;
+    *errorP = NULL;
+    return;
 
-error:
+cleanup:
     if (box) {
         jp2_box_destroy(box);
     }
     if (dec) {
         jp2_dec_destroy(dec);
     }
-    return 0;
 }
 
 
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c b/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c
index 4d4dfc50..140169ec 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c
@@ -114,15 +114,13 @@
  * $Id$
  */
 
-/*****************************************************************************\
-* Includes.
-\*****************************************************************************/
-
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <assert.h>
 
 #include "pm.h"
+#include "netpbm/nstring.h"
 
 #include "jasper/jas_types.h"
 #include "jasper/jas_math.h"
@@ -164,7 +162,10 @@ typedef struct {
     /* The states in which this type of marker segment can be
       validly encountered. */
 
-    int (*action)(jpc_dec_t *dec, jpc_ms_t *ms);
+    void (*action)(jpc_dec_t *   const dec,
+                   jpc_ms_t *    const ms,
+                   bool *        const doneP,
+                   const char ** const errorP);
     /* The action to take upon encountering this type of marker segment. */
 
 } jpc_dec_mstabent_t;
@@ -223,119 +224,263 @@ static void jpc_dec_cp_destroy(jpc_dec_cp_t *cp);
 static int jpc_dec_cp_setfrompoc(jpc_dec_cp_t *cp, jpc_poc_t *poc, int reset);
 static int jpc_pi_addpchgfrompoc(jpc_pi_t *pi, jpc_poc_t *poc);
 
-static int jpc_dec_decode(jpc_dec_t *dec);
 static jpc_dec_t *jpc_dec_create(jpc_dec_importopts_t *impopts, jas_stream_t *in);
 static void jpc_dec_destroy(jpc_dec_t *dec);
 static void jpc_dequantize(jas_matrix_t *x, jpc_fix_t absstepsize);
 static void jpc_undo_roi(jas_matrix_t *x, int roishift, int bgshift, int numbps);
 static jpc_fix_t jpc_calcabsstepsize(int stepsize, int numbits);
-static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile);
 static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile);
 static int jpc_dec_tilefini(jpc_dec_t *dec, jpc_dec_tile_t *tile);
-static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_eoc(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_cod(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_coc(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_rgn(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_qcd(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_qcc(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_poc(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_ppm(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_ppt(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_com(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_unk(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms);
-static int jpc_dec_parseopts(char *optstr, jpc_dec_importopts_t *opts);
 
-/******************************************************************************\
-* Global data.
-\******************************************************************************/
 
-jpc_dec_mstabent_t jpc_dec_mstab[] = {
-    {JPC_MS_SOC, JPC_MHSOC, jpc_dec_process_soc},
-    {JPC_MS_SOT, JPC_MH | JPC_TPHSOT, jpc_dec_process_sot},
-    {JPC_MS_SOD, JPC_TPH, jpc_dec_process_sod},
-    {JPC_MS_EOC, JPC_TPHSOT, jpc_dec_process_eoc},
-    {JPC_MS_SIZ, JPC_MHSIZ, jpc_dec_process_siz},
-    {JPC_MS_COD, JPC_MH | JPC_TPH, jpc_dec_process_cod},
-    {JPC_MS_COC, JPC_MH | JPC_TPH, jpc_dec_process_coc},
-    {JPC_MS_RGN, JPC_MH | JPC_TPH, jpc_dec_process_rgn},
-    {JPC_MS_QCD, JPC_MH | JPC_TPH, jpc_dec_process_qcd},
-    {JPC_MS_QCC, JPC_MH | JPC_TPH, jpc_dec_process_qcc},
-    {JPC_MS_POC, JPC_MH | JPC_TPH, jpc_dec_process_poc},
-    {JPC_MS_TLM, JPC_MH, 0},
-    {JPC_MS_PLM, JPC_MH, 0},
-    {JPC_MS_PLT, JPC_TPH, 0},
-    {JPC_MS_PPM, JPC_MH, jpc_dec_process_ppm},
-    {JPC_MS_PPT, JPC_TPH, jpc_dec_process_ppt},
-    {JPC_MS_SOP, 0, 0},
-    {JPC_MS_CRG, JPC_MH, jpc_dec_process_crg},
-    {JPC_MS_COM, JPC_MH | JPC_TPH, jpc_dec_process_com},
-    {0, JPC_MH | JPC_TPH, jpc_dec_process_unk}
-};
 
-/*****************************************************************************\
-* The main entry point for the JPEG-2000 decoder.
-\*****************************************************************************/
+static void
+jpc_dec_tiledecode(jpc_dec_t *      const dec,
+                   jpc_dec_tile_t * const tile,
+                   const char **    const errorP) {
 
-jas_image_t *jpc_decode(jas_stream_t *in, char *optstr)
-{
-    jpc_dec_importopts_t opts;
-    jpc_dec_t *dec;
-    jas_image_t *image;
+    int i;
+    int j;
+    jpc_dec_tcomp_t *tcomp;
+    jpc_dec_rlvl_t *rlvl;
+    jpc_dec_band_t *band;
+    int compno;
+    int rlvlno;
+    int bandno;
+    int adjust;
+    int v;
+    jpc_dec_ccp_t *ccp;
+    jpc_dec_cmpt_t *cmpt;
+    const char * error;
 
-    dec = 0;
+    jpc_dec_decodecblks(dec, tile, &error);
 
-    if (jpc_dec_parseopts(optstr, &opts)) {
-        goto error;
+    if (error) {
+        pm_asprintf(errorP, "jpc_dec_decodecblks failed.  %s", error);
+        return;
     }
 
-    jpc_initluts();
+    /* Perform dequantization. */
+    for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps;
+         ++compno, ++tcomp) {
+        ccp = &tile->cp->ccps[compno];
+        for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls;
+             ++rlvlno, ++rlvl) {
+            if (!rlvl->bands) {
+                continue;
+            }
+            for (bandno = 0, band = rlvl->bands;
+                 bandno < rlvl->numbands; ++bandno, ++band) {
+                if (!band->data) {
+                    continue;
+                }
+                jpc_undo_roi(band->data, band->roishift, ccp->roishift -
+                             band->roishift, band->numbps);
+                if (tile->realmode) {
+                    jas_matrix_asl(band->data, JPC_FIX_FRACBITS);
+                    jpc_dequantize(band->data, band->absstepsize);
+                }
 
-    if (!(dec = jpc_dec_create(&opts, in))) {
-        goto error;
+            }
+        }
     }
 
-    /* Do most of the work. */
-    if (jpc_dec_decode(dec)) {
-        goto error;
+    /* Apply an inverse wavelet transform if necessary. */
+    for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps;
+         ++compno, ++tcomp) {
+        ccp = &tile->cp->ccps[compno];
+        jpc_tsfb_synthesize(tcomp->tsfb,
+                            ((ccp->qmfbid ==
+                              JPC_COX_RFT) ? JPC_TSFB_RITIMODE : 0),
+                            tcomp->data);
     }
 
-    if (jas_image_numcmpts(dec->image) >= 3) {
-        jas_image_setcolorspace(dec->image, JAS_IMAGE_CS_RGB);
-        jas_image_setcmpttype(dec->image, 0,
-          JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R));
-        jas_image_setcmpttype(dec->image, 1,
-          JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G));
-        jas_image_setcmpttype(dec->image, 2,
-          JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B));
-    } else {
-        jas_image_setcolorspace(dec->image, JAS_IMAGE_CS_GRAY);
-        jas_image_setcmpttype(dec->image, 0,
-          JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y));
+
+    /* Apply an inverse intercomponent transform if necessary. */
+    switch (tile->cp->mctid) {
+    case JPC_MCT_RCT:
+        assert(dec->numcomps == 3);
+        jpc_irct(tile->tcomps[0].data, tile->tcomps[1].data,
+                 tile->tcomps[2].data);
+        break;
+    case JPC_MCT_ICT:
+        assert(dec->numcomps == 3);
+        jpc_iict(tile->tcomps[0].data, tile->tcomps[1].data,
+                 tile->tcomps[2].data);
+        break;
     }
 
-    /* Save the return value. */
-    image = dec->image;
+    /* Perform rounding and convert to integer values. */
+    if (tile->realmode) {
+        for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps;
+             ++compno, ++tcomp) {
+            for (i = 0; i < jas_matrix_numrows(tcomp->data); ++i) {
+                for (j = 0; j < jas_matrix_numcols(tcomp->data); ++j) {
+                    v = jas_matrix_get(tcomp->data, i, j);
+                    v = jpc_fix_round(v);
+                    jas_matrix_set(tcomp->data, i, j, jpc_fixtoint(v));
+                }
+            }
+        }
+    }
 
-    /* Stop the image from being discarded. */
-    dec->image = 0;
+    /* Perform level shift. */
+    for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno <
+             dec->numcomps; ++compno, ++tcomp, ++cmpt) {
+        adjust = cmpt->sgnd ? 0 : (1 << (cmpt->prec - 1));
+        for (i = 0; i < jas_matrix_numrows(tcomp->data); ++i) {
+            for (j = 0; j < jas_matrix_numcols(tcomp->data); ++j) {
+                *jas_matrix_getref(tcomp->data, i, j) += adjust;
+            }
+        }
+    }
 
-    /* Destroy decoder. */
-    jpc_dec_destroy(dec);
+    /* Perform clipping. */
+    for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno <
+             dec->numcomps; ++compno, ++tcomp, ++cmpt) {
+        jpc_fix_t mn;
+        jpc_fix_t mx;
+        mn = cmpt->sgnd ? (-(1 << (cmpt->prec - 1))) : (0);
+        mx = cmpt->sgnd ? ((1 << (cmpt->prec - 1)) - 1) : ((1 <<
+                                                            cmpt->prec) - 1);
+        jas_matrix_clip(tcomp->data, mn, mx);
+    }
 
-    return image;
+    /* XXX need to free tsfb struct */
 
-error:
-    if (dec) {
-        jpc_dec_destroy(dec);
+    /* Write the data for each component of the image. */
+    for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno <
+             dec->numcomps; ++compno, ++tcomp, ++cmpt) {
+        if (jas_image_writecmpt(dec->image, compno, tcomp->xstart -
+                                JPC_CEILDIV(dec->xstart, cmpt->hstep),
+                                tcomp->ystart -
+                                JPC_CEILDIV(dec->ystart, cmpt->vstep),
+                                jas_matrix_numcols(
+                                    tcomp->data),
+                                jas_matrix_numrows(tcomp->data),
+                                tcomp->data)) {
+            pm_asprintf(errorP, "write component failed");
+            return;
+        }
     }
-    return 0;
+    *errorP = NULL;
 }
 
+
+
+static void
+jpc_dec_process_sod(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
+    jpc_dec_tile_t *tile;
+    int pos;
+
+    if (!(tile = dec->curtile)) {
+        pm_asprintf(errorP, "No current tile");
+        return;
+    }
+
+    if (!tile->partno) {
+        if (!jpc_dec_cp_isvalid(tile->cp)) {
+            pm_asprintf(errorP, "CP is not valid");
+            return;
+        }
+        if (jpc_dec_cp_prepare(tile->cp)) {
+            pm_asprintf(errorP, "fpc_dec_cp_prepare failed");
+            return;
+        }
+        if (jpc_dec_tileinit(dec, tile)) {
+            pm_asprintf(errorP, "jpc_dec_tileinit failed");
+            return;
+        }
+    }
+
+    /* Are packet headers stored in the main header or tile-part header? */
+    if (dec->pkthdrstreams) {
+        /* Get the stream containing the packet header data for this
+          tile-part. */
+        if (!(tile->pkthdrstream = jpc_streamlist_remove(dec->pkthdrstreams, 0))) {
+            pm_asprintf(errorP, "jpc_streamlist_remove failed");
+            return;
+        }
+    }
+
+    if (tile->pptstab) {
+        if (!tile->pkthdrstream) {
+            if (!(tile->pkthdrstream = jas_stream_memopen(0, 0))) {
+                pm_asprintf(errorP, "jas_stream_memopen failed");
+                return;
+            }
+        }
+        pos = jas_stream_tell(tile->pkthdrstream);
+        jas_stream_seek(tile->pkthdrstream, 0, SEEK_END);
+        if (jpc_pptstabwrite(tile->pkthdrstream, tile->pptstab)) {
+            pm_asprintf(errorP, "jpc_pptstabwrite failed");
+            return;
+        }
+        jas_stream_seek(tile->pkthdrstream, pos, SEEK_SET);
+        jpc_ppxstab_destroy(tile->pptstab);
+        tile->pptstab = 0;
+    }
+
+    if (jas_getdbglevel() >= 10) {
+        jpc_dec_dump(dec, stderr);
+    }
+
+    if (jpc_dec_decodepkts(dec, (tile->pkthdrstream) ? tile->pkthdrstream :
+      dec->in, dec->in)) {
+        pm_asprintf(errorP, "jpc_dec_decodepkts failed");
+        return;
+    }
+
+    /* Gobble any unconsumed tile data. */
+    if (dec->curtileendoff > 0) {
+        uint_fast32_t curoff;
+        uint_fast32_t n;
+        curoff = jas_stream_getrwcount(dec->in);
+        if (curoff < dec->curtileendoff) {
+            n = dec->curtileendoff - curoff;
+            pm_message("warning: ignoring trailing garbage (%lu bytes)",
+                       (unsigned long) n);
+
+            while (n-- > 0) {
+                if (jas_stream_getc(dec->in) == EOF) {
+                    pm_asprintf(errorP, "read error");
+                    return;
+                }
+            }
+        } else if (curoff > dec->curtileendoff) {
+            pm_message("warning: not enough tile data (%lu bytes)",
+                       (unsigned long) curoff - dec->curtileendoff);
+        }
+    }
+
+    if (tile->numparts > 0 && tile->partno == tile->numparts - 1) {
+        const char * error;
+        jpc_dec_tiledecode(dec, tile, &error);
+        if (error) {
+            pm_asprintf(errorP, "jpc_dec_tiledecode failed.  %s", error);
+            pm_strfree(error);
+            return;
+        }
+        jpc_dec_tilefini(dec, tile);
+    }
+
+    dec->curtile = 0;
+
+    /* Increment the expected tile-part number. */
+    ++tile->partno;
+
+    /* We should expect to encounter a SOT marker segment next. */
+    dec->state = JPC_TPHSOT;
+
+    *errorP = NULL;
+}
+
+
+
 typedef enum {
     OPT_MAXLYRS,
     OPT_MAXPKTS,
@@ -349,7 +494,8 @@ jas_taginfo_t decopts[] = {
     {-1, 0}
 };
 
-static int jpc_dec_parseopts(char *optstr, jpc_dec_importopts_t *opts)
+static int
+jpc_dec_parseopts(const char *optstr, jpc_dec_importopts_t *opts)
 {
     jas_tvparser_t *tvp;
 
@@ -374,8 +520,8 @@ static int jpc_dec_parseopts(char *optstr, jpc_dec_importopts_t *opts)
             opts->maxpkts = atoi(jas_tvparser_getval(tvp));
             break;
         default:
-            fprintf(stderr, "warning: ignoring invalid option %s\n",
-              jas_tvparser_gettag(tvp));
+            pm_message("warning: ignoring invalid option %s",
+                       jas_tvparser_gettag(tvp));
             break;
         }
     }
@@ -385,79 +531,14 @@ static int jpc_dec_parseopts(char *optstr, jpc_dec_importopts_t *opts)
     return 0;
 }
 
-/******************************************************************************\
-* Code for table-driven code stream decoder.
-\******************************************************************************/
-
-static jpc_dec_mstabent_t *jpc_dec_mstab_lookup(uint_fast16_t id)
-{
-    jpc_dec_mstabent_t *mstabent;
-    for (mstabent = jpc_dec_mstab; mstabent->id != 0; ++mstabent) {
-        if (mstabent->id == id) {
-            break;
-        }
-    }
-    return mstabent;
-}
-
-static int jpc_dec_decode(jpc_dec_t *dec)
-{
-    jpc_ms_t *ms;
-    jpc_dec_mstabent_t *mstabent;
-    int ret;
-    jpc_cstate_t *cstate;
-
-    if (!(cstate = jpc_cstate_create())) {
-        return -1;
-    }
-    dec->cstate = cstate;
-
-    /* Initially, we should expect to encounter a SOC marker segment. */
-    dec->state = JPC_MHSOC;
-
-    for (;;) {
-
-        /* Get the next marker segment in the code stream. */
-        if (!(ms = jpc_getms(dec->in, cstate))) {
-            fprintf(stderr, "cannot get marker segment\n");
-            return -1;
-        }
-
-        mstabent = jpc_dec_mstab_lookup(ms->id);
-        assert(mstabent);
-
-        /* Ensure that this type of marker segment is permitted
-          at this point in the code stream. */
-        if (!(dec->state & mstabent->validstates)) {
-            fprintf(stderr, "unexpected marker segment type\n");
-            jpc_ms_destroy(ms);
-            return -1;
-        }
-
-        /* Process the marker segment. */
-        if (mstabent->action) {
-            ret = (*mstabent->action)(dec, ms);
-        } else {
-            /* No explicit action is required. */
-            ret = 0;
-        }
-
-        /* Destroy the marker segment. */
-        jpc_ms_destroy(ms);
-
-        if (ret < 0) {
-            return -1;
-        } else if (ret > 0) {
-            break;
-        }
 
-    }
 
-    return 0;
-}
+static void
+jpc_dec_process_crg(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
 
-static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms)
-{
     /* Ignore the information in the CRG marker segment for now.
        This information serves no useful purpose for decoding anyhow.
        Some other parts of the code need to be changed if these lines
@@ -475,19 +556,33 @@ static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms)
         cmpt->vsubstep = crg->comps[cmptno].voff;
     }
 #endif
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_soc(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     /* We should expect to encounter a SIZ marker segment next. */
     dec->state = JPC_MHSIZ;
 
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_sot(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_dec_tile_t *tile;
     jpc_sot_t *sot = &ms->parms.sot;
     jas_image_cmptparm_t *compinfos;
@@ -512,8 +607,9 @@ static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms)
         }
 
         if (!(dec->image = jas_image_create(dec->numcomps, compinfos,
-          JAS_IMAGE_CS_UNKNOWN))) {
-            return -1;
+                                            JAS_IMAGE_CS_UNKNOWN))) {
+            pm_asprintf(errorP, "jas_image_create failed");
+            return;
         }
         jas_free(compinfos);
 
@@ -538,18 +634,20 @@ static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms)
     }
 
     if (sot->tileno > dec->numtiles) {
-        fprintf(stderr, "invalid tile number in SOT marker segment\n");
-        return -1;
+        pm_asprintf(errorP, "invalid tile number in SOT marker segment");
+        return;
     }
     /* Set the current tile. */
     dec->curtile = &dec->tiles[sot->tileno];
     tile = dec->curtile;
     /* Ensure that this is the expected part number. */
     if (sot->partno != tile->partno) {
-        return -1;
+        pm_asprintf(errorP, "Unexpected part number");
+        return;
     }
     if (tile->numparts > 0 && sot->partno >= tile->numparts) {
-        return -1;
+        pm_asprintf(errorP, "part number greater than number of parts");
+        return;
     }
     if (!tile->numparts && sot->numparts > 0) {
         tile->numparts = sot->numparts;
@@ -563,7 +661,8 @@ static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms)
         tile->state = JPC_TILE_ACTIVE;
         assert(!tile->cp);
         if (!(tile->cp = jpc_dec_cp_copy(dec->cp))) {
-            return -1;
+            pm_asprintf(errorP, "jpc_dec_cp_copy failed");
+            return;
         }
         jpc_dec_cp_resetflags(dec->cp);
         break;
@@ -581,107 +680,11 @@ static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms)
       segments next. */
     dec->state = JPC_TPH;
 
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms)
-{
-    jpc_dec_tile_t *tile;
-    int pos;
-
-    if (!(tile = dec->curtile)) {
-        return -1;
-    }
-
-    if (!tile->partno) {
-        if (!jpc_dec_cp_isvalid(tile->cp)) {
-            return -1;
-        }
-        if (jpc_dec_cp_prepare(tile->cp)) {
-            return -1;
-        }
-        if (jpc_dec_tileinit(dec, tile)) {
-            return -1;
-        }
-    }
-
-    /* Are packet headers stored in the main header or tile-part header? */
-    if (dec->pkthdrstreams) {
-        /* Get the stream containing the packet header data for this
-          tile-part. */
-        if (!(tile->pkthdrstream = jpc_streamlist_remove(dec->pkthdrstreams, 0))) {
-            return -1;
-        }
-    }
-
-    if (tile->pptstab) {
-        if (!tile->pkthdrstream) {
-            if (!(tile->pkthdrstream = jas_stream_memopen(0, 0))) {
-                return -1;
-            }
-        }
-        pos = jas_stream_tell(tile->pkthdrstream);
-        jas_stream_seek(tile->pkthdrstream, 0, SEEK_END);
-        if (jpc_pptstabwrite(tile->pkthdrstream, tile->pptstab)) {
-            return -1;
-        }
-        jas_stream_seek(tile->pkthdrstream, pos, SEEK_SET);
-        jpc_ppxstab_destroy(tile->pptstab);
-        tile->pptstab = 0;
-    }
-
-    if (jas_getdbglevel() >= 10) {
-        jpc_dec_dump(dec, stderr);
-    }
-
-    if (jpc_dec_decodepkts(dec, (tile->pkthdrstream) ? tile->pkthdrstream :
-      dec->in, dec->in)) {
-        fprintf(stderr, "jpc_dec_decodepkts failed\n");
-        return -1;
-    }
-
-    /* Gobble any unconsumed tile data. */
-    if (dec->curtileendoff > 0) {
-        uint_fast32_t curoff;
-        uint_fast32_t n;
-        curoff = jas_stream_getrwcount(dec->in);
-        if (curoff < dec->curtileendoff) {
-            n = dec->curtileendoff - curoff;
-            fprintf(stderr,
-              "warning: ignoring trailing garbage (%lu bytes)\n",
-              (unsigned long) n);
-
-            while (n-- > 0) {
-                if (jas_stream_getc(dec->in) == EOF) {
-                    fprintf(stderr, "read error\n");
-                    return -1;
-                }
-            }
-        } else if (curoff > dec->curtileendoff) {
-            fprintf(stderr,
-              "warning: not enough tile data (%lu bytes)\n",
-              (unsigned long) curoff - dec->curtileendoff);
-        }
-
-    }
-
-    if (tile->numparts > 0 && tile->partno == tile->numparts - 1) {
-        if (jpc_dec_tiledecode(dec, tile)) {
-            return -1;
-        }
-        jpc_dec_tilefini(dec, tile);
-    }
-
-    dec->curtile = 0;
-
-    /* Increment the expected tile-part number. */
-    ++tile->partno;
-
-    /* We should expect to encounter a SOT marker segment next. */
-    dec->state = JPC_TPHSOT;
 
-    return 0;
-}
 
 static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile)
 {
@@ -1059,136 +1062,25 @@ if (!prc->cblks) {
     return 0;
 }
 
-static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile)
-{
-    int i;
-    int j;
-    jpc_dec_tcomp_t *tcomp;
-    jpc_dec_rlvl_t *rlvl;
-    jpc_dec_band_t *band;
-    int compno;
-    int rlvlno;
-    int bandno;
-    int adjust;
-    int v;
-    jpc_dec_ccp_t *ccp;
-    jpc_dec_cmpt_t *cmpt;
 
-    if (jpc_dec_decodecblks(dec, tile)) {
-        fprintf(stderr, "jpc_dec_decodecblks failed\n");
-        return -1;
-    }
 
-    /* Perform dequantization. */
-    for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps;
-      ++compno, ++tcomp) {
-        ccp = &tile->cp->ccps[compno];
-        for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls;
-          ++rlvlno, ++rlvl) {
-            if (!rlvl->bands) {
-                continue;
-            }
-            for (bandno = 0, band = rlvl->bands;
-              bandno < rlvl->numbands; ++bandno, ++band) {
-                if (!band->data) {
-                    continue;
-                }
-                jpc_undo_roi(band->data, band->roishift, ccp->roishift -
-                  band->roishift, band->numbps);
-                if (tile->realmode) {
-                    jas_matrix_asl(band->data, JPC_FIX_FRACBITS);
-                    jpc_dequantize(band->data, band->absstepsize);
-                }
+static void
+jpc_dec_process_eoc(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
 
-            }
-        }
-    }
-
-    /* Apply an inverse wavelet transform if necessary. */
-    for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps;
-      ++compno, ++tcomp) {
-        ccp = &tile->cp->ccps[compno];
-        jpc_tsfb_synthesize(tcomp->tsfb, ((ccp->qmfbid ==
-          JPC_COX_RFT) ? JPC_TSFB_RITIMODE : 0), tcomp->data);
-    }
-
-
-    /* Apply an inverse intercomponent transform if necessary. */
-    switch (tile->cp->mctid) {
-    case JPC_MCT_RCT:
-        assert(dec->numcomps == 3);
-        jpc_irct(tile->tcomps[0].data, tile->tcomps[1].data,
-          tile->tcomps[2].data);
-        break;
-    case JPC_MCT_ICT:
-        assert(dec->numcomps == 3);
-        jpc_iict(tile->tcomps[0].data, tile->tcomps[1].data,
-          tile->tcomps[2].data);
-        break;
-    }
-
-    /* Perform rounding and convert to integer values. */
-    if (tile->realmode) {
-        for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps;
-          ++compno, ++tcomp) {
-            for (i = 0; i < jas_matrix_numrows(tcomp->data); ++i) {
-                for (j = 0; j < jas_matrix_numcols(tcomp->data); ++j) {
-                    v = jas_matrix_get(tcomp->data, i, j);
-                    v = jpc_fix_round(v);
-                    jas_matrix_set(tcomp->data, i, j, jpc_fixtoint(v));
-                }
-            }
-        }
-    }
-
-    /* Perform level shift. */
-    for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno <
-      dec->numcomps; ++compno, ++tcomp, ++cmpt) {
-        adjust = cmpt->sgnd ? 0 : (1 << (cmpt->prec - 1));
-        for (i = 0; i < jas_matrix_numrows(tcomp->data); ++i) {
-            for (j = 0; j < jas_matrix_numcols(tcomp->data); ++j) {
-                *jas_matrix_getref(tcomp->data, i, j) += adjust;
-            }
-        }
-    }
-
-    /* Perform clipping. */
-    for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno <
-      dec->numcomps; ++compno, ++tcomp, ++cmpt) {
-        jpc_fix_t mn;
-        jpc_fix_t mx;
-        mn = cmpt->sgnd ? (-(1 << (cmpt->prec - 1))) : (0);
-        mx = cmpt->sgnd ? ((1 << (cmpt->prec - 1)) - 1) : ((1 <<
-          cmpt->prec) - 1);
-        jas_matrix_clip(tcomp->data, mn, mx);
-    }
-
-    /* XXX need to free tsfb struct */
-
-    /* Write the data for each component of the image. */
-    for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno <
-      dec->numcomps; ++compno, ++tcomp, ++cmpt) {
-        if (jas_image_writecmpt(dec->image, compno, tcomp->xstart -
-          JPC_CEILDIV(dec->xstart, cmpt->hstep), tcomp->ystart -
-          JPC_CEILDIV(dec->ystart, cmpt->vstep), jas_matrix_numcols(
-          tcomp->data), jas_matrix_numrows(tcomp->data), tcomp->data)) {
-            fprintf(stderr, "write component failed\n");
-            return -4;
-        }
-    }
-
-    return 0;
-}
-
-static int jpc_dec_process_eoc(jpc_dec_t *dec, jpc_ms_t *ms)
-{
     int tileno;
     jpc_dec_tile_t *tile;
     for (tileno = 0, tile = dec->tiles; tileno < dec->numtiles; ++tileno,
       ++tile) {
         if (tile->state == JPC_TILE_ACTIVE) {
-            if (jpc_dec_tiledecode(dec, tile)) {
-                return -1;
+            const char * error;
+            jpc_dec_tiledecode(dec, tile, &error);
+            if (error) {
+                pm_asprintf(errorP, "jpc_dec_tiledecode failed.  %s", error);
+                pm_strfree(error);
+                return;
             }
         }
         jpc_dec_tilefini(dec, tile);
@@ -1197,11 +1089,17 @@ static int jpc_dec_process_eoc(jpc_dec_t *dec, jpc_ms_t *ms)
     /* We are done processing the code stream. */
     dec->state = JPC_MT;
 
-    return 1;
+    *doneP = true;
 }
 
-static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_siz(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_siz_t *siz = &ms->parms.siz;
     uint_fast16_t compno;
     uint_fast32_t tileno;
@@ -1221,11 +1119,13 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms)
     dec->tileyoff = siz->tileyoff;
     dec->numcomps = siz->numcomps;
     if (!(dec->cp = jpc_dec_cp_create(dec->numcomps))) {
-        return -1;
+        pm_asprintf(errorP, "jpc_dec_cp_create failed");
+        return;
     }
 
     if (!(dec->cmpts = jas_malloc(dec->numcomps * sizeof(jpc_dec_cmpt_t)))) {
-        return -1;
+        pm_asprintf(errorP, "jas_malloc failed");
+        return;
     }
 
     for (compno = 0, cmpt = dec->cmpts; compno < dec->numcomps; ++compno,
@@ -1248,7 +1148,8 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms)
     dec->numvtiles = JPC_CEILDIV(dec->yend - dec->tileyoff, dec->tileheight);
     dec->numtiles = dec->numhtiles * dec->numvtiles;
     if (!(dec->tiles = jas_malloc(dec->numtiles * sizeof(jpc_dec_tile_t)))) {
-        return -1;
+        pm_asprintf(errorP, "jas_malloc failed");
+        return;
     }
 
     for (tileno = 0, tile = dec->tiles;
@@ -1280,9 +1181,10 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms)
         tile->pkthdrstreampos = 0;
         tile->pptstab = 0;
         tile->cp = 0;
-        if (!(tile->tcomps = jas_malloc(dec->numcomps *
-          sizeof(jpc_dec_tcomp_t)))) {
-            return -1;
+        tile->tcomps = jas_malloc(dec->numcomps * sizeof(jpc_dec_tcomp_t));
+        if (!tile->tcomps) {
+            pm_asprintf(errorP, "jas_malloc failed");
+            return;
         }
         for (compno = 0, cmpt = dec->cmpts, tcomp = tile->tcomps;
           compno < dec->numcomps; ++compno, ++cmpt, ++tcomp) {
@@ -1302,11 +1204,18 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms)
       or an SOT marker segment next. */
     dec->state = JPC_MH;
 
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_cod(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_cod(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_cod_t *cod = &ms->parms.cod;
     jpc_dec_tile_t *tile;
 
@@ -1316,26 +1225,34 @@ static int jpc_dec_process_cod(jpc_dec_t *dec, jpc_ms_t *ms)
         break;
     case JPC_TPH:
         if (!(tile = dec->curtile)) {
-            return -1;
+            pm_asprintf(errorP, "No current tile");
+            return;
         }
         if (tile->partno != 0) {
-            return -1;
+            pm_asprintf(errorP, "part number is not zero");
+            return;
         }
         jpc_dec_cp_setfromcod(tile->cp, cod);
         break;
     }
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_coc(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_coc(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_coc_t *coc = &ms->parms.coc;
     jpc_dec_tile_t *tile;
 
     if (coc->compno > dec->numcomps) {
-        fprintf(stderr,
-          "invalid component number in COC marker segment\n");
-        return -1;
+        pm_asprintf(errorP, "invalid component number in COC marker segment");
+        return;
     }
     switch (dec->state) {
     case JPC_MH:
@@ -1343,26 +1260,34 @@ static int jpc_dec_process_coc(jpc_dec_t *dec, jpc_ms_t *ms)
         break;
     case JPC_TPH:
         if (!(tile = dec->curtile)) {
-            return -1;
+            pm_asprintf(errorP, "No current tile");
+            return;
         }
         if (tile->partno > 0) {
-            return -1;
+            pm_asprintf(errorP, "Part number is not zero");
+            return;
         }
         jpc_dec_cp_setfromcoc(tile->cp, coc);
         break;
     }
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_rgn(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_rgn(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_rgn_t *rgn = &ms->parms.rgn;
     jpc_dec_tile_t *tile;
 
     if (rgn->compno > dec->numcomps) {
-        fprintf(stderr,
-          "invalid component number in RGN marker segment\n");
-        return -1;
+        pm_asprintf(errorP, "invalid component number in RGN marker segment");
+        return;
     }
     switch (dec->state) {
     case JPC_MH:
@@ -1370,20 +1295,29 @@ static int jpc_dec_process_rgn(jpc_dec_t *dec, jpc_ms_t *ms)
         break;
     case JPC_TPH:
         if (!(tile = dec->curtile)) {
-            return -1;
+            pm_asprintf(errorP, "No current tile");
+            return;
         }
         if (tile->partno > 0) {
-            return -1;
+            pm_asprintf(errorP, "Part number is not zero");
+            return;
         }
         jpc_dec_cp_setfromrgn(tile->cp, rgn);
         break;
     }
 
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_qcd(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_qcd(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_qcd_t *qcd = &ms->parms.qcd;
     jpc_dec_tile_t *tile;
 
@@ -1393,26 +1327,34 @@ static int jpc_dec_process_qcd(jpc_dec_t *dec, jpc_ms_t *ms)
         break;
     case JPC_TPH:
         if (!(tile = dec->curtile)) {
-            return -1;
+            pm_asprintf(errorP, "No current tile");
+            return;
         }
         if (tile->partno > 0) {
-            return -1;
+            pm_asprintf(errorP, "Part number is not zero");
+            return;
         }
         jpc_dec_cp_setfromqcd(tile->cp, qcd);
         break;
     }
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_qcc(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_qcc(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_qcc_t *qcc = &ms->parms.qcc;
     jpc_dec_tile_t *tile;
 
     if (qcc->compno > dec->numcomps) {
-        fprintf(stderr,
-          "invalid component number in QCC marker segment\n");
-        return -1;
+        pm_asprintf(errorP, "invalid component number in QCC marker segment");
+        return;
     }
     switch (dec->state) {
     case JPC_MH:
@@ -1420,69 +1362,98 @@ static int jpc_dec_process_qcc(jpc_dec_t *dec, jpc_ms_t *ms)
         break;
     case JPC_TPH:
         if (!(tile = dec->curtile)) {
-            return -1;
+            pm_asprintf(errorP, "No current tile");
+            return;
         }
         if (tile->partno > 0) {
-            return -1;
+            pm_asprintf(errorP, "Part number is not zero");
+            return;
         }
         jpc_dec_cp_setfromqcc(tile->cp, qcc);
         break;
     }
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_poc(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_poc(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_poc_t *poc = &ms->parms.poc;
     jpc_dec_tile_t *tile;
     switch (dec->state) {
     case JPC_MH:
         if (jpc_dec_cp_setfrompoc(dec->cp, poc, 1)) {
-            return -1;
+            pm_asprintf(errorP, "jpc_dec_cp_setfrompoc failed");
+            return;
         }
         break;
     case JPC_TPH:
         if (!(tile = dec->curtile)) {
-            return -1;
+            pm_asprintf(errorP, "No current tile");
+            return;
         }
         if (!tile->partno) {
             if (jpc_dec_cp_setfrompoc(tile->cp, poc, (!tile->partno))) {
-                return -1;
+                pm_asprintf(errorP, "jpc_dec_cp_setfrompoc failed");
+                return;
             }
         } else {
             jpc_pi_addpchgfrompoc(tile->pi, poc);
         }
         break;
     }
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_ppm(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_ppm(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_ppm_t *ppm = &ms->parms.ppm;
     jpc_ppxstabent_t *ppmstabent;
 
     if (!dec->ppmstab) {
         if (!(dec->ppmstab = jpc_ppxstab_create())) {
-            return -1;
+            pm_asprintf(errorP, "jpc_ppxstab_create failed");
+            return;
         }
     }
 
     if (!(ppmstabent = jpc_ppxstabent_create())) {
-        return -1;
+        pm_asprintf(errorP, "jpc_ppxstabent_create failed");
+        return;
     }
     ppmstabent->ind = ppm->ind;
     ppmstabent->data = ppm->data;
     ppm->data = 0;
     ppmstabent->len = ppm->len;
     if (jpc_ppxstab_insert(dec->ppmstab, ppmstabent)) {
-        return -1;
+        pm_asprintf(errorP, "jpc_ppxstab_insert failed");
+        return;
     }
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_ppt(jpc_dec_t *dec, jpc_ms_t *ms)
-{
+
+
+static void
+jpc_dec_process_ppt(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
     jpc_ppt_t *ppt = &ms->parms.ppt;
     jpc_dec_tile_t *tile;
     jpc_ppxstabent_t *pptstabent;
@@ -1490,34 +1461,55 @@ static int jpc_dec_process_ppt(jpc_dec_t *dec, jpc_ms_t *ms)
     tile = dec->curtile;
     if (!tile->pptstab) {
         if (!(tile->pptstab = jpc_ppxstab_create())) {
-            return -1;
+            pm_asprintf(errorP, "jpc_ppxstab_create failed");
+            return;
         }
     }
     if (!(pptstabent = jpc_ppxstabent_create())) {
-        return -1;
+        pm_asprintf(errorP, "jpc_ppxstabent_create failed");
+        return;
     }
     pptstabent->ind = ppt->ind;
     pptstabent->data = ppt->data;
     ppt->data = 0;
     pptstabent->len = ppt->len;
     if (jpc_ppxstab_insert(tile->pptstab, pptstabent)) {
-        return -1;
+        pm_asprintf(errorP, "jpc_ppxstab_insert failed.");
+        return;
     }
-    return 0;
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_com(jpc_dec_t *dec, jpc_ms_t *ms)
-{
-    return 0;
+
+
+static void
+jpc_dec_process_com(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
+    *doneP = false;
+    *errorP = NULL;
 }
 
-static int jpc_dec_process_unk(jpc_dec_t *dec, jpc_ms_t *ms)
-{
-    fprintf(stderr, "warning: ignoring unknown marker segment\n");
+
+
+static void
+jpc_dec_process_unk(jpc_dec_t *   const dec,
+                    jpc_ms_t *    const ms,
+                    bool *        const doneP,
+                    const char ** const errorP) {
+
+    pm_message("warning: ignoring unknown marker segment");
     jpc_ms_dump(ms, stderr);
-    return 0;
+
+    *doneP = false;
+    *errorP = NULL;
 }
 
+
+
 /******************************************************************************\
 *
 \******************************************************************************/
@@ -2370,3 +2362,168 @@ void jpc_ppxstabent_destroy(jpc_ppxstabent_t *ent)
     }
     jas_free(ent);
 }
+
+
+
+jpc_dec_mstabent_t jpc_dec_mstab[] = {
+    {JPC_MS_SOC, JPC_MHSOC, jpc_dec_process_soc},
+    {JPC_MS_SOT, JPC_MH | JPC_TPHSOT, jpc_dec_process_sot},
+    {JPC_MS_SOD, JPC_TPH, jpc_dec_process_sod},
+    {JPC_MS_EOC, JPC_TPHSOT, jpc_dec_process_eoc},
+    {JPC_MS_SIZ, JPC_MHSIZ, jpc_dec_process_siz},
+    {JPC_MS_COD, JPC_MH | JPC_TPH, jpc_dec_process_cod},
+    {JPC_MS_COC, JPC_MH | JPC_TPH, jpc_dec_process_coc},
+    {JPC_MS_RGN, JPC_MH | JPC_TPH, jpc_dec_process_rgn},
+    {JPC_MS_QCD, JPC_MH | JPC_TPH, jpc_dec_process_qcd},
+    {JPC_MS_QCC, JPC_MH | JPC_TPH, jpc_dec_process_qcc},
+    {JPC_MS_POC, JPC_MH | JPC_TPH, jpc_dec_process_poc},
+    {JPC_MS_TLM, JPC_MH, 0},
+    {JPC_MS_PLM, JPC_MH, 0},
+    {JPC_MS_PLT, JPC_TPH, 0},
+    {JPC_MS_PPM, JPC_MH, jpc_dec_process_ppm},
+    {JPC_MS_PPT, JPC_TPH, jpc_dec_process_ppt},
+    {JPC_MS_SOP, 0, 0},
+    {JPC_MS_CRG, JPC_MH, jpc_dec_process_crg},
+    {JPC_MS_COM, JPC_MH | JPC_TPH, jpc_dec_process_com},
+    {0, JPC_MH | JPC_TPH, jpc_dec_process_unk}
+};
+
+
+
+static jpc_dec_mstabent_t *jpc_dec_mstab_lookup(uint_fast16_t id)
+{
+    jpc_dec_mstabent_t *mstabent;
+    for (mstabent = jpc_dec_mstab; mstabent->id != 0; ++mstabent) {
+        if (mstabent->id == id) {
+            break;
+        }
+    }
+    return mstabent;
+}
+
+
+
+static void
+jpc_dec_decode(jpc_dec_t *   const dec,
+               const char ** const errorP) {
+
+    jpc_ms_t *ms;
+    jpc_dec_mstabent_t *mstabent;
+    bool done;
+    jpc_cstate_t *cstate;
+
+    if (!(cstate = jpc_cstate_create())) {
+        pm_asprintf(errorP, "jpc_cstate_create failed");
+        return;
+    }
+    dec->cstate = cstate;
+
+    /* Initially, we should expect to encounter a SOC marker segment. */
+    dec->state = JPC_MHSOC;
+
+    *errorP = NULL;   /* initial value */
+
+    for (;;) {
+
+        /* Get the next marker segment in the code stream. */
+        if (!(ms = jpc_getms(dec->in, cstate))) {
+            pm_asprintf(errorP, "cannot get marker segment");
+            return;
+        }
+
+        mstabent = jpc_dec_mstab_lookup(ms->id);
+        assert(mstabent);
+
+        /* Ensure that this type of marker segment is permitted
+          at this point in the code stream. */
+        if (!(dec->state & mstabent->validstates)) {
+            pm_asprintf(errorP, "unexpected marker segment type");
+            jpc_ms_destroy(ms);
+            return;
+        }
+
+        /* Process the marker segment. */
+        if (mstabent->action) {
+            (*mstabent->action)(dec, ms, &done, errorP);
+        } else {
+            /* No explicit action is required. */
+            *errorP = NULL;
+            done = false;
+        }
+
+        /* Destroy the marker segment. */
+        jpc_ms_destroy(ms);
+
+        if (*errorP) {
+            return;
+        } else if (done) {
+            break;
+        }
+    }
+}
+
+
+
+/*****************************************************************************\
+* The main entry point for the JPEG-2000 decoder.
+\*****************************************************************************/
+
+void
+jpc_decode(jas_stream_t * const in,
+           const char *   const optstr,
+           jas_image_t ** const imagePP,
+           const char **  const errorP) {
+
+    jpc_dec_importopts_t opts;
+    jpc_dec_t *dec;
+    jas_image_t *image;
+    const char * error;
+
+    if (jpc_dec_parseopts(optstr, &opts)) {
+        pm_asprintf(errorP, "jpc_dec_parseopts failed");
+        return;
+    }
+
+    jpc_initluts();
+
+    dec = jpc_dec_create(&opts, in);
+
+    if (!dec) {
+        pm_asprintf(errorP, "jpc_dec_create failed");
+    } else {
+        /* Do most of the work. */
+        jpc_dec_decode(dec, &error);
+        if (error) {
+            pm_asprintf(errorP, "jpc_dec_decode failed.  %s", error);
+            pm_strfree(error);
+        } else {
+            if (jas_image_numcmpts(dec->image) >= 3) {
+                jas_image_setcolorspace(dec->image, JAS_IMAGE_CS_RGB);
+                jas_image_setcmpttype(dec->image, 0,
+                                      JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R));
+                jas_image_setcmpttype(dec->image, 1,
+                                      JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G));
+                jas_image_setcmpttype(dec->image, 2,
+                                      JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B));
+            } else {
+                jas_image_setcolorspace(dec->image, JAS_IMAGE_CS_GRAY);
+                jas_image_setcmpttype(dec->image, 0,
+                                      JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y));
+            }
+
+            /* Save the return value. */
+            image = dec->image;
+
+            /* Stop the image from being discarded. */
+            dec->image = 0;
+
+            *imagePP = image;
+
+            *errorP = NULL;
+        }
+        jpc_dec_destroy(dec);
+    }
+}
+
+
+
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_dec.h b/converter/other/jpeg2000/libjasper/jpc/jpc_dec.h
index 02c5553d..fe0e9616 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_dec.h
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_dec.h
@@ -236,7 +236,7 @@ typedef struct {
 
 } jpc_dec_ccp_t;
 
-/* Coding paramters. */
+/* Coding parameters. */
 
 typedef struct {
 
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_enc.h b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.h
index cfd754c9..86a8e59c 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.h
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.h
@@ -145,7 +145,7 @@
 * Coding parameters types.
 \******************************************************************************/
 
-/* Per-component coding paramters. */
+/* Per-component coding parameters. */
 
 typedef struct {
 
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_mqenc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_mqenc.c
index 3f6122e3..54472481 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_mqenc.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_mqenc.c
@@ -6,14 +6,14 @@
  */
 
 /* __START_OF_JASPER_LICENSE__
- * 
+ *
  * JasPer Software License
- * 
+ *
  * IMAGE POWER JPEG-2000 PUBLIC LICENSE
  * ************************************
- * 
+ *
  * GRANT:
- * 
+ *
  * Permission is hereby granted, free of charge, to any person (the "User")
  * obtaining a copy of this software and associated documentation, to deal
  * in the JasPer Software without restriction, including without limitation
@@ -21,22 +21,22 @@
  * and/or sell copies of the JasPer Software (in source and binary forms),
  * and to permit persons to whom the JasPer Software is furnished to do so,
  * provided further that the License Conditions below are met.
- * 
+ *
  * License Conditions
  * ******************
- * 
+ *
  * A.  Redistributions of source code must retain the above copyright notice,
  * and this list of conditions, and the following disclaimer.
- * 
+ *
  * B.  Redistributions in binary form must reproduce the above copyright
  * notice, and this list of conditions, and the following disclaimer in
  * the documentation and/or other materials provided with the distribution.
- * 
+ *
  * C.  Neither the name of Image Power, Inc. nor any other contributor
  * (including, but not limited to, the University of British Columbia and
  * Michael David Adams) may be used to endorse or promote products derived
  * from this software without specific prior written permission.
- * 
+ *
  * D.  User agrees that it shall not commence any action against Image Power,
  * Inc., the University of British Columbia, Michael David Adams, or any
  * other contributors (collectively "Licensors") for infringement of any
@@ -56,17 +56,17 @@
  * trade dress, or service mark rights); and (v) divisions, continuations,
  * renewals, reissues and extensions of the foregoing (as and to the extent
  * applicable) now existing, hereafter filed, issued or acquired.
- * 
+ *
  * E.  If User commences an infringement action against any Licensor(s) then
  * such Licensor(s) shall have the right to terminate User's license and
  * all sublicenses that have been granted hereunder by User to other parties.
- * 
+ *
  * F.  This software is for use only in hardware or software products that
  * are compliant with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1).  No license
  * or right to this Software is granted for products that do not comply
  * with ISO/IEC 15444-1.  The JPEG-2000 Part 1 standard can be purchased
  * from the ISO.
- * 
+ *
  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
  * NO USE OF THE JASPER SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  * THIS DISCLAIMER.  THE JASPER SOFTWARE IS PROVIDED BY THE LICENSORS AND
@@ -106,7 +106,7 @@
  * TECHNOLOGY OR PRODUCTS FOR HIGH RISK ACTIVITIES AND WILL ENSURE THAT ITS
  * CUSTOMERS AND END-USERS OF ITS PRODUCTS ARE PROVIDED WITH A COPY OF THE
  * NOTICE SPECIFIED IN THIS SECTION.
- * 
+ *
  * __END_OF_JASPER_LICENSE__
  */
 
@@ -223,7 +223,7 @@
 }
 
 /******************************************************************************\
-* Local function protoypes.
+* Local function prototypes.
 \******************************************************************************/
 
 static void jpc_mqenc_setbits(jpc_mqenc_t *mqenc);
@@ -439,3 +439,6 @@ int jpc_mqenc_dump(jpc_mqenc_t *mqenc, FILE *out)
             (unsigned)(*mqenc->curctx)->qeval);
     return 0;
 }
+
+
+
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.c b/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.c
index 01a54ea8..b6c5e14f 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.c
@@ -124,6 +124,8 @@
 #include <stdlib.h>
 #include <assert.h>
 
+#include "netpbm/nstring.h"
+
 #include "jasper/jas_fix.h"
 #include "jasper/jas_stream.h"
 #include "jasper/jas_math.h"
@@ -138,817 +140,871 @@
 *
 \******************************************************************************/
 
-static int jpc_dec_decodecblk(jpc_dec_t *dec, jpc_dec_tile_t *tile, jpc_dec_tcomp_t *tcomp, jpc_dec_band_t *band,
-  jpc_dec_cblk_t *cblk, int dopartial, int maxlyrs);
-static int dec_sigpass(jpc_dec_t *dec, jpc_mqdec_t *mqdec, int bitpos, int orient,
-  int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data);
-static int dec_rawsigpass(jpc_dec_t *dec, jpc_bitstream_t *in, int bitpos,
-  int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data);
-static int dec_refpass(jpc_dec_t *dec, jpc_mqdec_t *mqdec, int bitpos, int vcausalflag,
-  jas_matrix_t *flags, jas_matrix_t *data);
-static int dec_rawrefpass(jpc_dec_t *dec, jpc_bitstream_t *in, int bitpos,
-  int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data);
-static int dec_clnpass(jpc_dec_t *dec, jpc_mqdec_t *mqdec, int bitpos, int orient,
-  int vcausalflag, int segsymflag, jas_matrix_t *flags, jas_matrix_t *data);
-
 #if defined(DEBUG)
 static long t1dec_cnt = 0;
 #endif
 
 #if !defined(DEBUG)
-#define	JPC_T1D_GETBIT(mqdec, v, passtypename, symtypename) \
-	((v) = jpc_mqdec_getbit(mqdec))
+#define JPC_T1D_GETBIT(mqdec, v, passtypename, symtypename) \
+    ((v) = jpc_mqdec_getbit(mqdec))
 #else
-#define	JPC_T1D_GETBIT(mqdec, v, passtypename, symtypename) \
+#define JPC_T1D_GETBIT(mqdec, v, passtypename, symtypename) \
 { \
-	(v) = jpc_mqdec_getbit(mqdec); \
-	if (jas_getdbglevel() >= 100) { \
-		fprintf(stderr, "index = %ld; passtype = %s; symtype = %s; sym = %d\n", t1dec_cnt, passtypename, symtypename, v); \
-		++t1dec_cnt; \
-	} \
+    (v) = jpc_mqdec_getbit(mqdec); \
+    if (jas_getdbglevel() >= 100) { \
+        fprintf(stderr, "index = %ld; passtype = %s; symtype = %s; sym = %d\n", t1dec_cnt, passtypename, symtypename, v); \
+        ++t1dec_cnt; \
+    } \
 }
 #endif
-#define	JPC_T1D_GETBITNOSKEW(mqdec, v, passtypename, symtypename) \
-	JPC_T1D_GETBIT(mqdec, v, passtypename, symtypename)
+#define JPC_T1D_GETBITNOSKEW(mqdec, v, passtypename, symtypename) \
+    JPC_T1D_GETBIT(mqdec, v, passtypename, symtypename)
 
 #if !defined(DEBUG)
-#define	JPC_T1D_RAWGETBIT(bitstream, v, passtypename, symtypename) \
-	((v) = jpc_bitstream_getbit(bitstream))
+#define JPC_T1D_RAWGETBIT(bitstream, v, passtypename, symtypename) \
+    ((v) = jpc_bitstream_getbit(bitstream))
 #else
-#define	JPC_T1D_RAWGETBIT(bitstream, v, passtypename, symtypename) \
+#define JPC_T1D_RAWGETBIT(bitstream, v, passtypename, symtypename) \
 { \
-	(v) = jpc_bitstream_getbit(bitstream); \
-	if (jas_getdbglevel() >= 100) { \
-		fprintf(stderr, "index = %ld; passtype = %s; symtype = %s; sym = %d\n", t1dec_cnt, passtypename, symtypename, v); \
-		++t1dec_cnt; \
-	} \
+    (v) = jpc_bitstream_getbit(bitstream); \
+    if (jas_getdbglevel() >= 100) { \
+        fprintf(stderr, "index = %ld; passtype = %s; symtype = %s; sym = %d\n", t1dec_cnt, passtypename, symtypename, v); \
+        ++t1dec_cnt; \
+    } \
 }
 #endif
 
-/******************************************************************************\
-* Code.
-\******************************************************************************/
 
-int jpc_dec_decodecblks(jpc_dec_t *dec, jpc_dec_tile_t *tile)
-{
-	jpc_dec_tcomp_t *tcomp;
-	int compcnt;
-	jpc_dec_rlvl_t *rlvl;
-	int rlvlcnt;
-	jpc_dec_band_t *band;
-	int bandcnt;
-	jpc_dec_prc_t *prc;
-	int prccnt;
-	jpc_dec_cblk_t *cblk;
-	int cblkcnt;
-
-	for (compcnt = dec->numcomps, tcomp = tile->tcomps; compcnt > 0;
-	  --compcnt, ++tcomp) {
-		for (rlvlcnt = tcomp->numrlvls, rlvl = tcomp->rlvls;
-		  rlvlcnt > 0; --rlvlcnt, ++rlvl) {
-			if (!rlvl->bands) {
-				continue;
-			}
-			for (bandcnt = rlvl->numbands, band = rlvl->bands;
-			  bandcnt > 0; --bandcnt, ++band) {
-				if (!band->data) {
-					continue;
-				}
-				for (prccnt = rlvl->numprcs, prc = band->prcs;
-				  prccnt > 0; --prccnt, ++prc) {
-					if (!prc->cblks) {
-						continue;
-					}
-					for (cblkcnt = prc->numcblks,
-					  cblk = prc->cblks; cblkcnt > 0;
-					  --cblkcnt, ++cblk) {
-						if (jpc_dec_decodecblk(dec, tile, tcomp,
-						  band, cblk, 1, JPC_MAXLYRS)) {
-							return -1;
-						}
-					}
-				}
-
-			}
-		}
-	}
-
-	return 0;
-}
-
-static int jpc_dec_decodecblk(jpc_dec_t *dec, jpc_dec_tile_t *tile, jpc_dec_tcomp_t *tcomp, jpc_dec_band_t *band,
-  jpc_dec_cblk_t *cblk, int dopartial, int maxlyrs)
-{
-	jpc_dec_seg_t *seg;
-	int i;
-	int bpno;
-	int passtype;
-	int ret;
-	int compno;
-	int filldata;
-	int fillmask;
-	jpc_dec_ccp_t *ccp;
-
-	compno = tcomp - tile->tcomps;
-
-	if (!cblk->flags) {
-		/* Note: matrix is assumed to be zeroed */
-		if (!(cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) +
-		  2, jas_matrix_numcols(cblk->data) + 2))) {
-			return -1;
-		}
-	}
-
-	seg = cblk->segs.head;
-	while (seg && (seg != cblk->curseg || dopartial) && (maxlyrs < 0 ||
-	  seg->lyrno < maxlyrs)) {
-		assert(seg->numpasses >= seg->maxpasses || dopartial);
-		assert(seg->stream);
-		jas_stream_rewind(seg->stream);
-		jas_stream_setrwcount(seg->stream, 0);
-		if (seg->type == JPC_SEG_MQ) {
-			if (!cblk->mqdec) {
-				if (!(cblk->mqdec = jpc_mqdec_create(JPC_NUMCTXS, 0))) {
-					return -1;
-				}
-				jpc_mqdec_setctxs(cblk->mqdec, JPC_NUMCTXS, jpc_mqctxs);
-			}
-			jpc_mqdec_setinput(cblk->mqdec, seg->stream);
-			jpc_mqdec_init(cblk->mqdec);
-		} else {
-			assert(seg->type == JPC_SEG_RAW);
-			if (!cblk->nulldec) {
-				if (!(cblk->nulldec = jpc_bitstream_sopen(seg->stream, "r"))) {
-					assert(0);
-				}
-			}
-		}
-
-
-		for (i = 0; i < seg->numpasses; ++i) {
-			if (cblk->numimsbs > band->numbps) {
-				ccp = &tile->cp->ccps[compno];
-				if (ccp->roishift <= 0) {
-					fprintf(stderr, "warning: corrupt code stream\n");
-				} else {
-					if (cblk->numimsbs < ccp->roishift - band->numbps) {
-						fprintf(stderr, "warning: corrupt code stream\n");
-					}
-				}
-			}
-			bpno = band->roishift + band->numbps - 1 - (cblk->numimsbs +
-			  (seg->passno + i - cblk->firstpassno + 2) / 3);
-if (bpno < 0) {
-	goto premature_exit;
-}
-#if 1
-			passtype = (seg->passno + i + 2) % 3;
-#else
-			passtype = JPC_PASSTYPE(seg->passno + i + 2);
-#endif
-			assert(bpno >= 0 && bpno < 31);
-			switch (passtype) {
-			case JPC_SIGPASS:
-				ret = (seg->type == JPC_SEG_MQ) ? dec_sigpass(dec,
-				  cblk->mqdec, bpno, band->orient,
-				  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
-				  cblk->flags, cblk->data) :
-				  dec_rawsigpass(dec, cblk->nulldec, bpno,
-				  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
-				  cblk->flags, cblk->data);
-				break;
-			case JPC_REFPASS:
-				ret = (seg->type == JPC_SEG_MQ) ?
-				  dec_refpass(dec, cblk->mqdec, bpno,
-				  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
-				  cblk->flags, cblk->data) :
-				  dec_rawrefpass(dec, cblk->nulldec, bpno,
-				  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
-				  cblk->flags, cblk->data);
-				break;
-			case JPC_CLNPASS:
-				assert(seg->type == JPC_SEG_MQ);
-				ret = dec_clnpass(dec, cblk->mqdec, bpno,
-				  band->orient, (tile->cp->ccps[compno].cblkctx &
-				  JPC_COX_VSC) != 0, (tile->cp->ccps[compno].cblkctx &
-				  JPC_COX_SEGSYM) != 0, cblk->flags,
-				  cblk->data);
-				break;
-			default:
-				ret = -1;
-				break;
-			}
-			/* Do we need to reset after each coding pass? */
-			if (tile->cp->ccps[compno].cblkctx & JPC_COX_RESET) {
-				jpc_mqdec_setctxs(cblk->mqdec, JPC_NUMCTXS, jpc_mqctxs);
-			}
-
-			if (ret) {
-				fprintf(stderr, "coding pass failed passtype=%d segtype=%d\n", passtype, seg->type);
-				return -1;
-			}
-
-		}
-
-		if (seg->type == JPC_SEG_MQ) {
-/* Note: dont destroy mq decoder because context info will be lost */
-		} else {
-			assert(seg->type == JPC_SEG_RAW);
-			if (tile->cp->ccps[compno].cblkctx & JPC_COX_PTERM) {
-				fillmask = 0x7f;
-				filldata = 0x2a;
-			} else {
-				fillmask = 0;
-				filldata = 0;
-			}
-			if ((ret = jpc_bitstream_inalign(cblk->nulldec, fillmask,
-			  filldata)) < 0) {
-				return -1;
-			} else if (ret > 0) {
-				fprintf(stderr, "warning: bad termination pattern detected\n");
-			}
-			jpc_bitstream_close(cblk->nulldec);
-			cblk->nulldec = 0;
-		}
-
-		cblk->curseg = seg->next;
-		jpc_seglist_remove(&cblk->segs, seg);
-		jpc_seg_destroy(seg);
-		seg = cblk->curseg;
-	}
-
-	assert(dopartial ? (!cblk->curseg) : 1);
-
-premature_exit:
-	return 0;
-}
 
 /******************************************************************************\
 * Code for significance pass.
 \******************************************************************************/
 
-#define	jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf, orient, mqdec, vcausalflag) \
+#define jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf, orient, mqdec, vcausalflag) \
 { \
-	int f; \
-	int v; \
-	f = *(fp); \
-	if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
-		jpc_mqdec_setcurctx((mqdec), JPC_GETZCCTXNO(f, (orient))); \
-		JPC_T1D_GETBIT((mqdec), v, "SIG", "ZC"); \
-		if (v) { \
-			jpc_mqdec_setcurctx((mqdec), JPC_GETSCCTXNO(f)); \
-			JPC_T1D_GETBIT((mqdec), v, "SIG", "SC"); \
-			v ^= JPC_GETSPB(f); \
-			JPC_UPDATEFLAGS4((fp), (frowstep), v, (vcausalflag)); \
-			*(fp) |= JPC_SIG; \
-			*(dp) = (v) ? (-(oneplushalf)) : (oneplushalf); \
-		} \
-		*(fp) |= JPC_VISIT; \
-	} \
+    int f; \
+    int v; \
+    f = *(fp); \
+    if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
+        jpc_mqdec_setcurctx((mqdec), JPC_GETZCCTXNO(f, (orient))); \
+        JPC_T1D_GETBIT((mqdec), v, "SIG", "ZC"); \
+        if (v) { \
+            jpc_mqdec_setcurctx((mqdec), JPC_GETSCCTXNO(f)); \
+            JPC_T1D_GETBIT((mqdec), v, "SIG", "SC"); \
+            v ^= JPC_GETSPB(f); \
+            JPC_UPDATEFLAGS4((fp), (frowstep), v, (vcausalflag)); \
+            *(fp) |= JPC_SIG; \
+            *(dp) = (v) ? (-(oneplushalf)) : (oneplushalf); \
+        } \
+        *(fp) |= JPC_VISIT; \
+    } \
 }
 
-static int dec_sigpass(jpc_dec_t *dec, register jpc_mqdec_t *mqdec, int bitpos, int orient,
-  int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data)
-{
-	int i;
-	int j;
-	int one;
-	int half;
-	int oneplushalf;
-	int vscanlen;
-	int width;
-	int height;
-	jpc_fix_t *fp;
-	int frowstep;
-	int fstripestep;
-	jpc_fix_t *fstripestart;
-	jpc_fix_t *fvscanstart;
-	jpc_fix_t *dp;
-	int drowstep;
-	int dstripestep;
-	jpc_fix_t *dstripestart;
-	jpc_fix_t *dvscanstart;
-	int k;
-
-	width = jas_matrix_numcols(data);
-	height = jas_matrix_numrows(data);
-	frowstep = jas_matrix_rowstep(flags);
-	drowstep = jas_matrix_rowstep(data);
-	fstripestep = frowstep << 2;
-	dstripestep = drowstep << 2;
-
-	one = 1 << bitpos;
-	half = one >> 1;
-	oneplushalf = one | half;
-
-	fstripestart = jas_matrix_getref(flags, 1, 1);
-	dstripestart = jas_matrix_getref(data, 0, 0);
-	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
-	  dstripestart += dstripestep) {
-		fvscanstart = fstripestart;
-		dvscanstart = dstripestart;
-		vscanlen = JAS_MIN(i, 4);
-		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
-			fp = fvscanstart;
-			dp = dvscanstart;
-			k = vscanlen;
-
-			/* Process first sample in vertical scan. */
-			jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
-			  orient, mqdec, vcausalflag);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process second sample in vertical scan. */
-			jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
-			  orient, mqdec, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process third sample in vertical scan. */
-			jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
-			  orient, mqdec, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process fourth sample in vertical scan. */
-			jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
-			  orient, mqdec, 0);
-		}
-	}
-	return 0;
+#define jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf, in, vcausalflag) \
+{ \
+    jpc_fix_t f = *(fp); \
+    jpc_fix_t v; \
+    if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
+        JPC_T1D_RAWGETBIT(in, v, "SIG", "ZC"); \
+        if (v < 0) { \
+            return -1; \
+        } \
+        if (v) { \
+            JPC_T1D_RAWGETBIT(in, v, "SIG", "SC"); \
+            if (v < 0) { \
+                return -1; \
+            } \
+            JPC_UPDATEFLAGS4((fp), (frowstep), v, (vcausalflag)); \
+            *(fp) |= JPC_SIG; \
+            *(dp) = v ? (-oneplushalf) : (oneplushalf); \
+        } \
+        *(fp) |= JPC_VISIT; \
+    } \
 }
 
-#define	jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf, in, vcausalflag) \
-{ \
-	jpc_fix_t f = *(fp); \
-	jpc_fix_t v; \
-	if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
-		JPC_T1D_RAWGETBIT(in, v, "SIG", "ZC"); \
-		if (v < 0) { \
-			return -1; \
-		} \
-		if (v) { \
-			JPC_T1D_RAWGETBIT(in, v, "SIG", "SC"); \
-			if (v < 0) { \
-				return -1; \
-			} \
-			JPC_UPDATEFLAGS4((fp), (frowstep), v, (vcausalflag)); \
-			*(fp) |= JPC_SIG; \
-			*(dp) = v ? (-oneplushalf) : (oneplushalf); \
-		} \
-		*(fp) |= JPC_VISIT; \
-	} \
+
+
+static int
+dec_sigpass(jpc_dec_t *dec, register jpc_mqdec_t *mqdec, int bitpos,
+            int orient,
+            int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data)
+{
+    int i;
+    int j;
+    int one;
+    int half;
+    int oneplushalf;
+    int vscanlen;
+    int width;
+    int height;
+    jpc_fix_t *fp;
+    int frowstep;
+    int fstripestep;
+    jpc_fix_t *fstripestart;
+    jpc_fix_t *fvscanstart;
+    jpc_fix_t *dp;
+    int drowstep;
+    int dstripestep;
+    jpc_fix_t *dstripestart;
+    jpc_fix_t *dvscanstart;
+    int k;
+
+    width = jas_matrix_numcols(data);
+    height = jas_matrix_numrows(data);
+    frowstep = jas_matrix_rowstep(flags);
+    drowstep = jas_matrix_rowstep(data);
+    fstripestep = frowstep << 2;
+    dstripestep = drowstep << 2;
+
+    one = 1 << bitpos;
+    half = one >> 1;
+    oneplushalf = one | half;
+
+    fstripestart = jas_matrix_getref(flags, 1, 1);
+    dstripestart = jas_matrix_getref(data, 0, 0);
+    for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
+      dstripestart += dstripestep) {
+        fvscanstart = fstripestart;
+        dvscanstart = dstripestart;
+        vscanlen = JAS_MIN(i, 4);
+        for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
+            fp = fvscanstart;
+            dp = dvscanstart;
+            k = vscanlen;
+
+            /* Process first sample in vertical scan. */
+            jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
+              orient, mqdec, vcausalflag);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process second sample in vertical scan. */
+            jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
+              orient, mqdec, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process third sample in vertical scan. */
+            jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
+              orient, mqdec, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process fourth sample in vertical scan. */
+            jpc_sigpass_step(fp, frowstep, dp, bitpos, oneplushalf,
+              orient, mqdec, 0);
+        }
+    }
+    return 0;
 }
 
-static int dec_rawsigpass(jpc_dec_t *dec, jpc_bitstream_t *in, int bitpos, int vcausalflag,
-  jas_matrix_t *flags, jas_matrix_t *data)
+
+
+static int
+dec_rawsigpass(jpc_dec_t *dec, jpc_bitstream_t *in, int bitpos,
+               int vcausalflag,
+               jas_matrix_t *flags, jas_matrix_t *data)
 {
-	int i;
-	int j;
-	int k;
-	int one;
-	int half;
-	int oneplushalf;
-	int vscanlen;
-	int width;
-	int height;
-	jpc_fix_t *fp;
-	int frowstep;
-	int fstripestep;
-	jpc_fix_t *fstripestart;
-	jpc_fix_t *fvscanstart;
-	jpc_fix_t *dp;
-	int drowstep;
-	int dstripestep;
-	jpc_fix_t *dstripestart;
-	jpc_fix_t *dvscanstart;
-
-	width = jas_matrix_numcols(data);
-	height = jas_matrix_numrows(data);
-	frowstep = jas_matrix_rowstep(flags);
-	drowstep = jas_matrix_rowstep(data);
-	fstripestep = frowstep << 2;
-	dstripestep = drowstep << 2;
-
-	one = 1 << bitpos;
-	half = one >> 1;
-	oneplushalf = one | half;
-
-	fstripestart = jas_matrix_getref(flags, 1, 1);
-	dstripestart = jas_matrix_getref(data, 0, 0);
-	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
-	  dstripestart += dstripestep) {
-		fvscanstart = fstripestart;
-		dvscanstart = dstripestart;
-		vscanlen = JAS_MIN(i, 4);
-		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
-			fp = fvscanstart;
-			dp = dvscanstart;
-			k = vscanlen;
-
-			/* Process first sample in vertical scan. */
-			jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
-			  in, vcausalflag);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process second sample in vertical scan. */
-			jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
-			  in, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process third sample in vertical scan. */
-			jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
-			  in, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process fourth sample in vertical scan. */
-			jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
-			  in, 0);
-
-		}
-	}
-	return 0;
+    int i;
+    int j;
+    int k;
+    int one;
+    int half;
+    int oneplushalf;
+    int vscanlen;
+    int width;
+    int height;
+    jpc_fix_t *fp;
+    int frowstep;
+    int fstripestep;
+    jpc_fix_t *fstripestart;
+    jpc_fix_t *fvscanstart;
+    jpc_fix_t *dp;
+    int drowstep;
+    int dstripestep;
+    jpc_fix_t *dstripestart;
+    jpc_fix_t *dvscanstart;
+
+    width = jas_matrix_numcols(data);
+    height = jas_matrix_numrows(data);
+    frowstep = jas_matrix_rowstep(flags);
+    drowstep = jas_matrix_rowstep(data);
+    fstripestep = frowstep << 2;
+    dstripestep = drowstep << 2;
+
+    one = 1 << bitpos;
+    half = one >> 1;
+    oneplushalf = one | half;
+
+    fstripestart = jas_matrix_getref(flags, 1, 1);
+    dstripestart = jas_matrix_getref(data, 0, 0);
+    for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
+      dstripestart += dstripestep) {
+        fvscanstart = fstripestart;
+        dvscanstart = dstripestart;
+        vscanlen = JAS_MIN(i, 4);
+        for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
+            fp = fvscanstart;
+            dp = dvscanstart;
+            k = vscanlen;
+
+            /* Process first sample in vertical scan. */
+            jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
+              in, vcausalflag);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process second sample in vertical scan. */
+            jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
+              in, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process third sample in vertical scan. */
+            jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
+              in, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process fourth sample in vertical scan. */
+            jpc_rawsigpass_step(fp, frowstep, dp, oneplushalf,
+              in, 0);
+
+        }
+    }
+    return 0;
 }
 
+
+
 /******************************************************************************\
 * Code for refinement pass.
 \******************************************************************************/
 
-#define	jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, vcausalflag) \
+#define jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, vcausalflag) \
 { \
-	int v; \
-	int t; \
-	if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
-		jpc_mqdec_setcurctx((mqdec), JPC_GETMAGCTXNO(*(fp))); \
-		JPC_T1D_GETBITNOSKEW((mqdec), v, "REF", "MR"); \
-		t = (v ? (poshalf) : (neghalf)); \
-		*(dp) += (*(dp) < 0) ? (-t) : t; \
-		*(fp) |= JPC_REFINE; \
-	} \
+    int v; \
+    int t; \
+    if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
+        jpc_mqdec_setcurctx((mqdec), JPC_GETMAGCTXNO(*(fp))); \
+        JPC_T1D_GETBITNOSKEW((mqdec), v, "REF", "MR"); \
+        t = (v ? (poshalf) : (neghalf)); \
+        *(dp) += (*(dp) < 0) ? (-t) : t; \
+        *(fp) |= JPC_REFINE; \
+    } \
 }
 
-static int dec_refpass(jpc_dec_t *dec, register jpc_mqdec_t *mqdec, int bitpos,
-  int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data)
+
+
+static int
+dec_refpass(jpc_dec_t *dec, register jpc_mqdec_t *mqdec, int bitpos,
+            int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data)
 {
-	int i;
-	int j;
-	int vscanlen;
-	int width;
-	int height;
-	int one;
-	int poshalf;
-	int neghalf;
-	jpc_fix_t *fp;
-	int frowstep;
-	int fstripestep;
-	jpc_fix_t *fstripestart;
-	jpc_fix_t *fvscanstart;
-	jpc_fix_t *dp;
-	int drowstep;
-	int dstripestep;
-	jpc_fix_t *dstripestart;
-	jpc_fix_t *dvscanstart;
-	int k;
-
-	width = jas_matrix_numcols(data);
-	height = jas_matrix_numrows(data);
-	frowstep = jas_matrix_rowstep(flags);
-	drowstep = jas_matrix_rowstep(data);
-	fstripestep = frowstep << 2;
-	dstripestep = drowstep << 2;
-
-	one = 1 << bitpos;
-	poshalf = one >> 1;
-	neghalf = (bitpos > 0) ? (-poshalf) : (-1);
-
-	fstripestart = jas_matrix_getref(flags, 1, 1);
-	dstripestart = jas_matrix_getref(data, 0, 0);
-	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
-	  dstripestart += dstripestep) {
-		fvscanstart = fstripestart;
-		dvscanstart = dstripestart;
-		vscanlen = JAS_MIN(i, 4);
-		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
-			fp = fvscanstart;
-			dp = dvscanstart;
-			k = vscanlen;
-
-			/* Process first sample in vertical scan. */
-			jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec,
-			  vcausalflag);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process second sample in vertical scan. */
-			jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process third sample in vertical scan. */
-			jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process fourth sample in vertical scan. */
-			jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, 0);
-		}
-	}
-
-	return 0;
+    int i;
+    int j;
+    int vscanlen;
+    int width;
+    int height;
+    int one;
+    int poshalf;
+    int neghalf;
+    jpc_fix_t *fp;
+    int frowstep;
+    int fstripestep;
+    jpc_fix_t *fstripestart;
+    jpc_fix_t *fvscanstart;
+    jpc_fix_t *dp;
+    int drowstep;
+    int dstripestep;
+    jpc_fix_t *dstripestart;
+    jpc_fix_t *dvscanstart;
+    int k;
+
+    width = jas_matrix_numcols(data);
+    height = jas_matrix_numrows(data);
+    frowstep = jas_matrix_rowstep(flags);
+    drowstep = jas_matrix_rowstep(data);
+    fstripestep = frowstep << 2;
+    dstripestep = drowstep << 2;
+
+    one = 1 << bitpos;
+    poshalf = one >> 1;
+    neghalf = (bitpos > 0) ? (-poshalf) : (-1);
+
+    fstripestart = jas_matrix_getref(flags, 1, 1);
+    dstripestart = jas_matrix_getref(data, 0, 0);
+    for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
+      dstripestart += dstripestep) {
+        fvscanstart = fstripestart;
+        dvscanstart = dstripestart;
+        vscanlen = JAS_MIN(i, 4);
+        for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
+            fp = fvscanstart;
+            dp = dvscanstart;
+            k = vscanlen;
+
+            /* Process first sample in vertical scan. */
+            jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec,
+              vcausalflag);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process second sample in vertical scan. */
+            jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process third sample in vertical scan. */
+            jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process fourth sample in vertical scan. */
+            jpc_refpass_step(fp, dp, poshalf, neghalf, mqdec, 0);
+        }
+    }
+
+    return 0;
 }
 
-#define	jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, vcausalflag) \
+#define jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, vcausalflag) \
 { \
-	jpc_fix_t v; \
-	jpc_fix_t t; \
-	if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
-		JPC_T1D_RAWGETBIT(in, v, "REF", "MAGREF"); \
-		if (v < 0) { \
-			return -1; \
-		} \
-		t = (v ? poshalf : neghalf); \
-		*(dp) += (*(dp) < 0) ? (-t) : t; \
-		*(fp) |= JPC_REFINE; \
-	} \
+    jpc_fix_t v; \
+    jpc_fix_t t; \
+    if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
+        JPC_T1D_RAWGETBIT(in, v, "REF", "MAGREF"); \
+        if (v < 0) { \
+            return -1; \
+        } \
+        t = (v ? poshalf : neghalf); \
+        *(dp) += (*(dp) < 0) ? (-t) : t; \
+        *(fp) |= JPC_REFINE; \
+    } \
 }
 
-static int dec_rawrefpass(jpc_dec_t *dec, jpc_bitstream_t *in, int bitpos, int vcausalflag,
-  jas_matrix_t *flags, jas_matrix_t *data)
+
+
+static int
+dec_rawrefpass(jpc_dec_t *dec, jpc_bitstream_t *in, int bitpos,
+               int vcausalflag,
+               jas_matrix_t *flags, jas_matrix_t *data)
 {
-	int i;
-	int j;
-	int k;
-	int vscanlen;
-	int width;
-	int height;
-	int one;
-	int poshalf;
-	int neghalf;
-	jpc_fix_t *fp;
-	int frowstep;
-	int fstripestep;
-	jpc_fix_t *fstripestart;
-	jpc_fix_t *fvscanstart;
-	jpc_fix_t *dp;
-	int drowstep;
-	int dstripestep;
-	jpc_fix_t *dstripestart;
-	jpc_fix_t *dvscanstart;
-
-	width = jas_matrix_numcols(data);
-	height = jas_matrix_numrows(data);
-	frowstep = jas_matrix_rowstep(flags);
-	drowstep = jas_matrix_rowstep(data);
-	fstripestep = frowstep << 2;
-	dstripestep = drowstep << 2;
-
-	one = 1 << bitpos;
-	poshalf = one >> 1;
-	neghalf = (bitpos > 0) ? (-poshalf) : (-1);
-
-	fstripestart = jas_matrix_getref(flags, 1, 1);
-	dstripestart = jas_matrix_getref(data, 0, 0);
-	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
-	  dstripestart += dstripestep) {
-		fvscanstart = fstripestart;
-		dvscanstart = dstripestart;
-		vscanlen = JAS_MIN(i, 4);
-		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
-			fp = fvscanstart;
-			dp = dvscanstart;
-			k = vscanlen;
-
-			/* Process first sample in vertical scan. */
-			jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in,
-			  vcausalflag);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process second sample in vertical scan. */
-			jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process third sample in vertical scan. */
-			jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process fourth sample in vertical scan. */
-			jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, 0);
-		}
-	}
-	return 0;
+    int i;
+    int j;
+    int k;
+    int vscanlen;
+    int width;
+    int height;
+    int one;
+    int poshalf;
+    int neghalf;
+    jpc_fix_t *fp;
+    int frowstep;
+    int fstripestep;
+    jpc_fix_t *fstripestart;
+    jpc_fix_t *fvscanstart;
+    jpc_fix_t *dp;
+    int drowstep;
+    int dstripestep;
+    jpc_fix_t *dstripestart;
+    jpc_fix_t *dvscanstart;
+
+    width = jas_matrix_numcols(data);
+    height = jas_matrix_numrows(data);
+    frowstep = jas_matrix_rowstep(flags);
+    drowstep = jas_matrix_rowstep(data);
+    fstripestep = frowstep << 2;
+    dstripestep = drowstep << 2;
+
+    one = 1 << bitpos;
+    poshalf = one >> 1;
+    neghalf = (bitpos > 0) ? (-poshalf) : (-1);
+
+    fstripestart = jas_matrix_getref(flags, 1, 1);
+    dstripestart = jas_matrix_getref(data, 0, 0);
+    for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
+      dstripestart += dstripestep) {
+        fvscanstart = fstripestart;
+        dvscanstart = dstripestart;
+        vscanlen = JAS_MIN(i, 4);
+        for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
+            fp = fvscanstart;
+            dp = dvscanstart;
+            k = vscanlen;
+
+            /* Process first sample in vertical scan. */
+            jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in,
+              vcausalflag);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process second sample in vertical scan. */
+            jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process third sample in vertical scan. */
+            jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process fourth sample in vertical scan. */
+            jpc_rawrefpass_step(fp, dp, poshalf, neghalf, in, 0);
+        }
+    }
+    return 0;
 }
 
+
+
 /******************************************************************************\
 * Code for cleanup pass.
 \******************************************************************************/
 
-#define	jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient, mqdec, flabel, plabel, vcausalflag) \
+#define jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient, mqdec, flabel, plabel, vcausalflag) \
 { \
-	int v; \
+    int v; \
 flabel \
-	if (!((f) & (JPC_SIG | JPC_VISIT))) { \
-		jpc_mqdec_setcurctx((mqdec), JPC_GETZCCTXNO((f), (orient))); \
-		JPC_T1D_GETBIT((mqdec), v, "CLN", "ZC"); \
-		if (v) { \
+    if (!((f) & (JPC_SIG | JPC_VISIT))) { \
+        jpc_mqdec_setcurctx((mqdec), JPC_GETZCCTXNO((f), (orient))); \
+        JPC_T1D_GETBIT((mqdec), v, "CLN", "ZC"); \
+        if (v) { \
 plabel \
-			/* Coefficient is significant. */ \
-			jpc_mqdec_setcurctx((mqdec), JPC_GETSCCTXNO(f)); \
-			JPC_T1D_GETBIT((mqdec), v, "CLN", "SC"); \
-			v ^= JPC_GETSPB(f); \
-			*(dp) = (v) ? (-(oneplushalf)) : (oneplushalf); \
-			JPC_UPDATEFLAGS4((fp), (frowstep), v, (vcausalflag)); \
-			*(fp) |= JPC_SIG; \
-		} \
-	} \
-	/* XXX - Is this correct?  Can aggregation cause some VISIT bits not to be reset?  Check. */ \
-	*(fp) &= ~JPC_VISIT; \
+            /* Coefficient is significant. */ \
+            jpc_mqdec_setcurctx((mqdec), JPC_GETSCCTXNO(f)); \
+            JPC_T1D_GETBIT((mqdec), v, "CLN", "SC"); \
+            v ^= JPC_GETSPB(f); \
+            *(dp) = (v) ? (-(oneplushalf)) : (oneplushalf); \
+            JPC_UPDATEFLAGS4((fp), (frowstep), v, (vcausalflag)); \
+            *(fp) |= JPC_SIG; \
+        } \
+    } \
+    /* XXX - Is this correct?  Can aggregation cause some VISIT bits not to be reset?  Check. */ \
+    *(fp) &= ~JPC_VISIT; \
 }
 
-static int dec_clnpass(jpc_dec_t *dec, register jpc_mqdec_t *mqdec, int bitpos, int orient,
-  int vcausalflag, int segsymflag, jas_matrix_t *flags, jas_matrix_t *data)
+static int
+dec_clnpass(jpc_dec_t *dec, register jpc_mqdec_t *mqdec, int bitpos,
+            int orient, int vcausalflag, int segsymflag, jas_matrix_t *flags,
+            jas_matrix_t *data)
 {
-	int i;
-	int j;
-	int k;
-	int vscanlen;
-	int v;
-	int half;
-	int runlen;
-	int f;
-	int width;
-	int height;
-	int one;
-	int oneplushalf;
-
-	jpc_fix_t *fp;
-	int frowstep;
-	int fstripestep;
-	jpc_fix_t *fstripestart;
-	jpc_fix_t *fvscanstart;
-
-	jpc_fix_t *dp;
-	int drowstep;
-	int dstripestep;
-	jpc_fix_t *dstripestart;
-	jpc_fix_t *dvscanstart;
-
-	one = 1 << bitpos;
-	half = one >> 1;
-	oneplushalf = one | half;
-
-	width = jas_matrix_numcols(data);
-	height = jas_matrix_numrows(data);
-
-	frowstep = jas_matrix_rowstep(flags);
-	drowstep = jas_matrix_rowstep(data);
-	fstripestep = frowstep << 2;
-	dstripestep = drowstep << 2;
-
-	fstripestart = jas_matrix_getref(flags, 1, 1);
-	dstripestart = jas_matrix_getref(data, 0, 0);
-	for (i = 0; i < height; i += 4, fstripestart += fstripestep,
-	  dstripestart += dstripestep) {
-		fvscanstart = fstripestart;
-		dvscanstart = dstripestart;
-		vscanlen = JAS_MIN(4, height - i);
-		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
-			fp = fvscanstart;
-			if (vscanlen >= 4 && (!((*fp) & (JPC_SIG | JPC_VISIT |
-			  JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) & (JPC_SIG |
-			  JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) &
-			  (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep,
-			  !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) {
-
-				jpc_mqdec_setcurctx(mqdec, JPC_AGGCTXNO);
-				JPC_T1D_GETBIT(mqdec, v, "CLN", "AGG");
-				if (!v) {
-					continue;
-				}
-				jpc_mqdec_setcurctx(mqdec, JPC_UCTXNO);
-				JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "RL");
-				runlen = v;
-				JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "RL");
-				runlen = (runlen << 1) | v;
-				f = *(fp = fvscanstart + frowstep * runlen);
-				dp = dvscanstart + drowstep * runlen;
-				k = vscanlen - runlen;
-				switch (runlen) {
-				case 0:
-					goto clnpass_partial0;
-					break;
-				case 1:
-					goto clnpass_partial1;
-					break;
-				case 2:
-					goto clnpass_partial2;
-					break;
-				case 3:
-					goto clnpass_partial3;
-					break;
-				}
-			} else {
-				f = *(fp = fvscanstart);
-				dp = dvscanstart;
-				k = vscanlen;
-				goto clnpass_full0;
-			}
-
-			/* Process first sample in vertical scan. */
-			jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
-			  mqdec, clnpass_full0:, clnpass_partial0:,
-			  vcausalflag);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process second sample in vertical scan. */
-			f = *fp;
-			jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
-				mqdec, ;, clnpass_partial1:, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process third sample in vertical scan. */
-			f = *fp;
-			jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
-				mqdec, ;, clnpass_partial2:, 0);
-			if (--k <= 0) {
-				continue;
-			}
-			fp += frowstep;
-			dp += drowstep;
-
-			/* Process fourth sample in vertical scan. */
-			f = *fp;
-			jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
-				mqdec, ;, clnpass_partial3:, 0);
-		}
-	}
-
-	if (segsymflag) {
-		int segsymval;
-		segsymval = 0;
-		jpc_mqdec_setcurctx(mqdec, JPC_UCTXNO);
-		JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
-		segsymval = (segsymval << 1) | (v & 1);
-		JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
-		segsymval = (segsymval << 1) | (v & 1);
-		JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
-		segsymval = (segsymval << 1) | (v & 1);
-		JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
-		segsymval = (segsymval << 1) | (v & 1);
-		if (segsymval != 0xa) {
-			fprintf(stderr, "warning: bad segmentation symbol\n");
-		}
-	}
-
-	return 0;
+    int i;
+    int j;
+    int k;
+    int vscanlen;
+    int v;
+    int half;
+    int runlen;
+    int f;
+    int width;
+    int height;
+    int one;
+    int oneplushalf;
+
+    jpc_fix_t *fp;
+    int frowstep;
+    int fstripestep;
+    jpc_fix_t *fstripestart;
+    jpc_fix_t *fvscanstart;
+
+    jpc_fix_t *dp;
+    int drowstep;
+    int dstripestep;
+    jpc_fix_t *dstripestart;
+    jpc_fix_t *dvscanstart;
+
+    one = 1 << bitpos;
+    half = one >> 1;
+    oneplushalf = one | half;
+
+    width = jas_matrix_numcols(data);
+    height = jas_matrix_numrows(data);
+
+    frowstep = jas_matrix_rowstep(flags);
+    drowstep = jas_matrix_rowstep(data);
+    fstripestep = frowstep << 2;
+    dstripestep = drowstep << 2;
+
+    fstripestart = jas_matrix_getref(flags, 1, 1);
+    dstripestart = jas_matrix_getref(data, 0, 0);
+    for (i = 0; i < height; i += 4, fstripestart += fstripestep,
+      dstripestart += dstripestep) {
+        fvscanstart = fstripestart;
+        dvscanstart = dstripestart;
+        vscanlen = JAS_MIN(4, height - i);
+        for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
+            fp = fvscanstart;
+            if (vscanlen >= 4 && (!((*fp) & (JPC_SIG | JPC_VISIT |
+              JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) & (JPC_SIG |
+              JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) &
+              (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep,
+              !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) {
+
+                jpc_mqdec_setcurctx(mqdec, JPC_AGGCTXNO);
+                JPC_T1D_GETBIT(mqdec, v, "CLN", "AGG");
+                if (!v) {
+                    continue;
+                }
+                jpc_mqdec_setcurctx(mqdec, JPC_UCTXNO);
+                JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "RL");
+                runlen = v;
+                JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "RL");
+                runlen = (runlen << 1) | v;
+                f = *(fp = fvscanstart + frowstep * runlen);
+                dp = dvscanstart + drowstep * runlen;
+                k = vscanlen - runlen;
+                switch (runlen) {
+                case 0:
+                    goto clnpass_partial0;
+                    break;
+                case 1:
+                    goto clnpass_partial1;
+                    break;
+                case 2:
+                    goto clnpass_partial2;
+                    break;
+                case 3:
+                    goto clnpass_partial3;
+                    break;
+                }
+            } else {
+                f = *(fp = fvscanstart);
+                dp = dvscanstart;
+                k = vscanlen;
+                goto clnpass_full0;
+            }
+
+            /* Process first sample in vertical scan. */
+            jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
+              mqdec, clnpass_full0:, clnpass_partial0:,
+              vcausalflag);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process second sample in vertical scan. */
+            f = *fp;
+            jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
+                mqdec, ;, clnpass_partial1:, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process third sample in vertical scan. */
+            f = *fp;
+            jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
+                mqdec, ;, clnpass_partial2:, 0);
+            if (--k <= 0) {
+                continue;
+            }
+            fp += frowstep;
+            dp += drowstep;
+
+            /* Process fourth sample in vertical scan. */
+            f = *fp;
+            jpc_clnpass_step(f, fp, frowstep, dp, oneplushalf, orient,
+                mqdec, ;, clnpass_partial3:, 0);
+        }
+    }
+
+    if (segsymflag) {
+        int segsymval;
+        segsymval = 0;
+        jpc_mqdec_setcurctx(mqdec, JPC_UCTXNO);
+        JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
+        segsymval = (segsymval << 1) | (v & 1);
+        JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
+        segsymval = (segsymval << 1) | (v & 1);
+        JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
+        segsymval = (segsymval << 1) | (v & 1);
+        JPC_T1D_GETBITNOSKEW(mqdec, v, "CLN", "SEGSYM");
+        segsymval = (segsymval << 1) | (v & 1);
+        if (segsymval != 0xa) {
+            fprintf(stderr, "warning: bad segmentation symbol\n");
+        }
+    }
+
+    return 0;
+}
+
+
+
+static void
+jpc_dec_decodecblk(jpc_dec_t *       const dec,
+                   jpc_dec_tile_t *  const tile,
+                   jpc_dec_tcomp_t * const tcomp,
+                   jpc_dec_band_t *  const band,
+                   jpc_dec_cblk_t *  const cblk,
+                   int               const dopartial,
+                   int               const maxlyrs,
+                   const char **     const errorP) {
+
+    jpc_dec_seg_t *seg;
+    int i;
+    int bpno;
+    int passtype;
+    int ret;
+    int compno;
+    int filldata;
+    int fillmask;
+    jpc_dec_ccp_t *ccp;
+
+    compno = tcomp - tile->tcomps;
+
+    if (!cblk->flags) {
+        /* Note: matrix is assumed to be zeroed */
+        unsigned int const nrow = jas_matrix_numrows(cblk->data) + 2;
+        unsigned int const ncol = jas_matrix_numcols(cblk->data) + 2;
+        cblk->flags = jas_matrix_create(nrow, ncol);
+        if (!cblk->flags) {
+            pm_asprintf(errorP, "Out of memory allocating a flags matrix of "
+                        "%u rows by %u columns", nrow, ncol);
+            return;
+        }
+    }
+
+    seg = cblk->segs.head;
+    while (seg && (seg != cblk->curseg || dopartial) && (maxlyrs < 0 ||
+      seg->lyrno < maxlyrs)) {
+        assert(seg->numpasses >= seg->maxpasses || dopartial);
+        assert(seg->stream);
+        jas_stream_rewind(seg->stream);
+        jas_stream_setrwcount(seg->stream, 0);
+        if (seg->type == JPC_SEG_MQ) {
+            if (!cblk->mqdec) {
+                if (!(cblk->mqdec = jpc_mqdec_create(JPC_NUMCTXS, 0))) {
+                    pm_asprintf(errorP, "jpc_mqdec_create failed");
+                    return;
+                }
+                jpc_mqdec_setctxs(cblk->mqdec, JPC_NUMCTXS, jpc_mqctxs);
+            }
+            jpc_mqdec_setinput(cblk->mqdec, seg->stream);
+            jpc_mqdec_init(cblk->mqdec);
+        } else {
+            assert(seg->type == JPC_SEG_RAW);
+            if (!cblk->nulldec) {
+                if (!(cblk->nulldec = jpc_bitstream_sopen(seg->stream, "r"))) {
+                    assert(0);
+                }
+            }
+        }
+
+
+        for (i = 0; i < seg->numpasses; ++i) {
+            if (cblk->numimsbs > band->numbps) {
+                ccp = &tile->cp->ccps[compno];
+                if (ccp->roishift <= 0) {
+                    fprintf(stderr, "warning: corrupt code stream\n");
+                } else {
+                    if (cblk->numimsbs < ccp->roishift - band->numbps) {
+                        fprintf(stderr, "warning: corrupt code stream\n");
+                    }
+                }
+            }
+            bpno = band->roishift + band->numbps - 1 - (cblk->numimsbs +
+              (seg->passno + i - cblk->firstpassno + 2) / 3);
+            if (bpno < 0) {
+                goto exit;
+            }
+#if 1
+            passtype = (seg->passno + i + 2) % 3;
+#else
+            passtype = JPC_PASSTYPE(seg->passno + i + 2);
+#endif
+            assert(bpno >= 0 && bpno < 31);
+            switch (passtype) {
+            case JPC_SIGPASS:
+                ret = (seg->type == JPC_SEG_MQ) ? dec_sigpass(dec,
+                  cblk->mqdec, bpno, band->orient,
+                  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
+                  cblk->flags, cblk->data) :
+                  dec_rawsigpass(dec, cblk->nulldec, bpno,
+                  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
+                  cblk->flags, cblk->data);
+                break;
+            case JPC_REFPASS:
+                ret = (seg->type == JPC_SEG_MQ) ?
+                  dec_refpass(dec, cblk->mqdec, bpno,
+                  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
+                  cblk->flags, cblk->data) :
+                  dec_rawrefpass(dec, cblk->nulldec, bpno,
+                  (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0,
+                  cblk->flags, cblk->data);
+                break;
+            case JPC_CLNPASS:
+                assert(seg->type == JPC_SEG_MQ);
+                ret = dec_clnpass(dec, cblk->mqdec, bpno,
+                  band->orient, (tile->cp->ccps[compno].cblkctx &
+                  JPC_COX_VSC) != 0, (tile->cp->ccps[compno].cblkctx &
+                  JPC_COX_SEGSYM) != 0, cblk->flags,
+                  cblk->data);
+                break;
+            default:
+                ret = -1;
+                break;
+            }
+            /* Do we need to reset after each coding pass? */
+            if (tile->cp->ccps[compno].cblkctx & JPC_COX_RESET) {
+                jpc_mqdec_setctxs(cblk->mqdec, JPC_NUMCTXS, jpc_mqctxs);
+            }
+
+            if (ret) {
+                pm_asprintf(errorP,
+                            "coding pass failed passtype=%d segtype=%d",
+                            passtype, seg->type);
+                return;
+            }
+
+        }
+
+        if (seg->type == JPC_SEG_MQ) {
+            /* Note: dont destroy mq decoder because context info will be
+               lost
+            */
+        } else {
+            assert(seg->type == JPC_SEG_RAW);
+            if (tile->cp->ccps[compno].cblkctx & JPC_COX_PTERM) {
+                fillmask = 0x7f;
+                filldata = 0x2a;
+            } else {
+                fillmask = 0;
+                filldata = 0;
+            }
+            if ((ret = jpc_bitstream_inalign(cblk->nulldec, fillmask,
+              filldata)) < 0) {
+                pm_asprintf(errorP, "jpc_bitstream_inalign failed");
+                return;
+            } else if (ret > 0) {
+                pm_message("warning: bad termination pattern detected");
+            }
+            jpc_bitstream_close(cblk->nulldec);
+            cblk->nulldec = 0;
+        }
+
+        cblk->curseg = seg->next;
+        jpc_seglist_remove(&cblk->segs, seg);
+        jpc_seg_destroy(seg);
+        seg = cblk->curseg;
+    }
+
+    assert(dopartial ? (!cblk->curseg) : 1);
+
+exit:
+    *errorP = NULL;
 }
+
+
+
+void
+jpc_dec_decodecblks(jpc_dec_t *      const decP,
+                    jpc_dec_tile_t * const tileP,
+                    const char **    const errorP) {
+/*----------------------------------------------------------------------------
+  Decode all of the code blocks for a particular tile
+-----------------------------------------------------------------------------*/
+    unsigned int compcnt;
+    jpc_dec_tcomp_t * tcompP;
+
+    for (compcnt = 0, tcompP = tileP->tcomps;
+         compcnt < decP->numcomps;
+         ++compcnt, ++tcompP) {
+
+        unsigned int rlvlcnt;
+        jpc_dec_rlvl_t * rlvlP;
+
+        for (rlvlcnt = 0, rlvlP = tcompP->rlvls;
+             rlvlcnt < tcompP->numrlvls;
+             ++rlvlcnt, ++rlvlP) {
+
+            if (rlvlP->bands) {
+                unsigned int bandcnt;
+                jpc_dec_band_t * bandP;
+
+                for (bandcnt = 0, bandP = rlvlP->bands;
+                     bandcnt < rlvlP->numbands;
+                     ++bandcnt, ++bandP) {
+
+                    if (bandP->data) {
+                        unsigned int prccnt;
+                        jpc_dec_prc_t * prcP;
+
+                        for (prccnt = 0, prcP = bandP->prcs;
+                             prccnt < rlvlP->numprcs;
+                             ++prccnt, ++prcP) {
+
+                            if (prcP->cblks) {
+                                unsigned int cblkcnt;
+                                jpc_dec_cblk_t * cblkP;
+
+                                for (cblkcnt = 0, cblkP = prcP->cblks;
+                                     cblkcnt < prcP->numcblks;
+                                     ++cblkcnt, ++cblkP) {
+
+                                    const char * error;
+
+                                    jpc_dec_decodecblk(decP, tileP, tcompP,
+                                                       bandP, cblkP, 1,
+                                                       JPC_MAXLYRS, &error);
+                                    if (error) {
+                                        pm_asprintf(errorP,
+                                                    "jpc_dec_decodecblk "
+                                                    "failed on component %u, "
+                                                    "resolution level %u, "
+                                                    "band %u, prc %u, "
+                                                    "code block %u.  %s",
+                                                    compcnt, rlvlcnt, bandcnt,
+                                                    prccnt, cblkcnt, error);
+                                        pm_strfree(error);
+                                        return;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    *errorP = NULL;
+}
+
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.h b/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.h
index e28a1f57..f8b3b342 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.h
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_t1dec.h
@@ -119,19 +119,13 @@
 #ifndef JPC_T1DEC_H
 #define JPC_T1DEC_H
 
-/******************************************************************************\
-* Includes.
-\******************************************************************************/
-
 #include "jpc_dec.h"
 #include "jpc_mqdec.h"
 #include "jpc_t1cod.h"
 
-/******************************************************************************\
-* Functions.
-\******************************************************************************/
-
-/* Decode all of the code blocks for a particular tile. */
-int jpc_dec_decodecblks(jpc_dec_t *dec, jpc_dec_tile_t *tile);
+void
+jpc_dec_decodecblks(jpc_dec_t *      const decP,
+                    jpc_dec_tile_t * const tileP,
+                    const char **    const errorP);
 
 #endif
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/libjasper_compat.c b/converter/other/jpeg2000/libjasper_compat.c
new file mode 100644
index 00000000..101820a3
--- /dev/null
+++ b/converter/other/jpeg2000/libjasper_compat.c
@@ -0,0 +1,26 @@
+#include "netpbm/nstring.h"
+
+#include "jasper/jasper.h"
+#include "jasper/jas_image.h"
+
+#ifndef JAS_HAVE_PMJAS_IMAGE_DECODE
+
+void
+pmjas_image_decode(jas_stream_t * const in,
+                   int            const fmtArg,
+                   const char *   const optstr,
+                   jas_image_t ** const imagePP,
+                   const char **  const errorP) {
+
+    jas_image_t * const jasperP = jas_image_decode(in, fmtArg, optstr);
+
+    if (jasperP) {
+        *imagePP = jasperP;
+        *errorP  = errorP;
+    } else {
+        pm_asprintf(errorP, "Failed.  Details may have been written to "
+                    "Standard Error");
+    }
+}
+
+#endif
diff --git a/converter/other/jpeg2000/libjasper_compat.h b/converter/other/jpeg2000/libjasper_compat.h
index 401144a3..103b1d09 100644
--- a/converter/other/jpeg2000/libjasper_compat.h
+++ b/converter/other/jpeg2000/libjasper_compat.h
@@ -1,12 +1,18 @@
 /* Here's some stuff to create backward compatibility with older Jasper
    libraries.  Unfortunately, new versions of the Jasper library are not
    backward compatible with old applications.
+
+   This also makes the programs compatible with both distributed Jasper
+   libraries and the Netpbm fork of Jasper distributed with Netpbm.
 */
 /* The color space thing got more complex between Version 1.600 and
    1.701.  For example, it now allows for multiple kinds of RGB, whereas
    in 1.600 RGB meant SRGB.  As part of that change, names changed
    from "colorspace" to "clrspc".
 */
+#include "jasper/jasper.h"
+#include "jasper/jas_image.h"
+
 #if defined(jas_image_setcolorspace)
 /* Old style color space */
 #define jas_image_setclrspc jas_image_setcolorspace
@@ -22,3 +28,32 @@
 #define JAS_CLRSPC_FAM_UNKNOWN JAS_IMAGE_CS_UNKNOWN
 
 #endif
+
+
+#ifndef JAS_HAVE_PMJAS_IMAGE_DECODE
+
+/* The Netpbm version of jas_image_decode (pmjas_image_decode) returns a
+   description of the problem when it fails and does not molest Standard
+   Error.  Real libjasper just indicates that it failed, after writing some
+   explanation (but not as much as the Netpbm version returns) to Standard
+   Error.
+*/
+void
+pmjas_image_decode(jas_stream_t * const in,
+                   int            const fmtArg,
+                   const char *   const optstr,
+                   jas_image_t ** const imagePP,
+                   const char **  const errorP) {
+
+    jas_image_t * const jasperP = jas_image_decode(in, fmtArg, optstr);
+
+    if (jasperP) {
+        *imagePP = jasperP;
+        *errorP  = NULL;
+    } else {
+        pm_asprintf(errorP, "Failed.  Details may have been written to "
+                    "Standard Error");
+    }
+}
+
+#endif
diff --git a/converter/other/jpeg2000/pamtojpeg2k.c b/converter/other/jpeg2000/pamtojpeg2k.c
index a886c390..8f7409c0 100644
--- a/converter/other/jpeg2000/pamtojpeg2k.c
+++ b/converter/other/jpeg2000/pamtojpeg2k.c
@@ -35,7 +35,7 @@ enum compmode {COMPMODE_INTEGER, COMPMODE_REAL};
 
 enum progression {PROG_LRCP, PROG_RLCP, PROG_RPCL, PROG_PCRL, PROG_CPRL};
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
@@ -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;
@@ -73,10 +75,10 @@ struct cmdlineInfo {
 
 static void
 parseCommandLine(int argc, char ** argv,
-                 struct cmdlineInfo * const cmdlineP) {
+                 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)
@@ -372,9 +379,11 @@ convertToJasperImage(struct pam *   const inpamP,
 
 static void
 writeJpc(jas_image_t *      const jasperP,
-         struct cmdlineInfo const cmdline,
-         FILE *             const ofP) {
-
+         struct CmdlineInfo const cmdline,
+         int                const ofd) {
+/*----------------------------------------------------------------------------
+   Write the image *jasperP to open file 'ofd'.
+-----------------------------------------------------------------------------*/
     jas_stream_t * outStreamP;
     const char * options;
     const char * ilyrratesOpt;
@@ -403,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
@@ -459,7 +470,7 @@ writeJpc(jas_image_t *      const jasperP,
     pm_strfree(ilyrratesOpt);
 
     /* Open the output image file (Standard Output) */
-    outStreamP = jas_stream_fdopen(fileno(ofP), "w+b");
+    outStreamP = jas_stream_fdopen(ofd, "w+b");
     if (outStreamP == NULL)
         pm_error("Unable to open output stream.  jas_stream_fdopen() "
                  "failed");
@@ -500,7 +511,7 @@ writeJpc(jas_image_t *      const jasperP,
 int
 main(int argc, char **argv)
 {
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     struct pam inpam;
     jas_image_t * jasperP;
@@ -526,7 +537,7 @@ main(int argc, char **argv)
 
     convertToJasperImage(&inpam, &jasperP);
 
-    writeJpc(jasperP, cmdline, stdout);
+    writeJpc(jasperP, cmdline, fileno(stdout));
 
 	jas_image_destroy(jasperP);