about summary refs log tree commit diff
path: root/converter/other
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2014-06-29 19:43:45 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2014-06-29 19:43:45 +0000
commitfcd1b680c260b931cb5b8cd900c88d9e8dd5f1ad (patch)
tree798e7e0a8fc53429b26d536ecb6ec1a176923ded /converter/other
parent51eb5e0d2722f0cf1033ac158d2fdbcd82b6e800 (diff)
downloadnetpbm-mirror-fcd1b680c260b931cb5b8cd900c88d9e8dd5f1ad.tar.gz
netpbm-mirror-fcd1b680c260b931cb5b8cd900c88d9e8dd5f1ad.tar.xz
netpbm-mirror-fcd1b680c260b931cb5b8cd900c88d9e8dd5f1ad.zip
Fix up commit mess
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@2223 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other')
-rw-r--r--converter/other/Makefile128
-rw-r--r--converter/other/cameratopam/Makefile14
-rw-r--r--converter/other/exif.c1197
-rw-r--r--converter/other/exif.h22
-rw-r--r--converter/other/fiasco/Makefile16
-rw-r--r--converter/other/fiasco/codec/ip.c4
-rw-r--r--converter/other/fiasco/codec/tiling.c2
-rw-r--r--converter/other/fiasco/codec/wfa.h2
-rw-r--r--converter/other/fiasco/display.c3
-rw-r--r--converter/other/fiasco/lib/image.c2
-rw-r--r--converter/other/fiasco/params.c2
-rw-r--r--converter/other/fiasco/pnmtofiasco.c2
-rw-r--r--converter/other/jbig/ANNOUNCE243
-rw-r--r--converter/other/jbig/Makefile32
-rw-r--r--converter/other/jbig/README.Netpbm12
-rw-r--r--converter/other/jbig/jbig.c2905
-rw-r--r--converter/other/jbig/jbig.doc721
-rw-r--r--converter/other/jbig/jbig.h267
-rw-r--r--converter/other/jbig/jbig_tab.c428
-rw-r--r--converter/other/jbig/jbigtopnm.c2
-rw-r--r--converter/other/jpeg2000/Makefile13
-rw-r--r--converter/other/jpeg2000/jpeg2ktopam.c3
-rw-r--r--converter/other/jpeg2000/libjasper/base/jas_image.c2
-rw-r--r--converter/other/jpeg2000/libjasper/include/jasper/jas_image.h38
-rw-r--r--converter/other/jpeg2000/libjasper/jp2/jp2_dec.c4
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_cs.c2
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_enc.c2
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c8
-rw-r--r--converter/other/jpeg2000/pamtojpeg2k.c3
-rw-r--r--converter/other/jpegtopnm.c12
-rw-r--r--converter/other/pamtosvg/Makefile32
-rw-r--r--converter/other/pamtosvg/bitmap.h2
-rw-r--r--converter/other/pamtosvg/image-proc.c2
-rw-r--r--converter/other/pamtosvg/thin-image.c2
-rw-r--r--converter/other/pamtotiff.c452
-rw-r--r--converter/other/pnmtopalm/Makefile16
-rw-r--r--converter/other/pnmtopalm/gen_palm_colormap.c4
-rw-r--r--converter/other/pnmtosgi.c512
-rw-r--r--converter/other/sgi.h8
-rw-r--r--converter/other/sgitopnm.c86
-rw-r--r--converter/other/tifftopnm.c6
41 files changed, 1433 insertions, 5780 deletions
diff --git a/converter/other/Makefile b/converter/other/Makefile
index 1a44017f..bbc40a3f 100644
--- a/converter/other/Makefile
+++ b/converter/other/Makefile
@@ -117,46 +117,38 @@ PORTBINARIES =  avstopam bmptopnm fitstopnm \
 		gemtopnm giftopnm hdifftopam infotopam \
 		pamtoavs pamtodjvurle pamtofits pamtogif \
 		pamtohdiff pamtohtmltbl pamtompfont pamtooctaveimg \
-		pamtopam pamtopfm pamtopnm pamtouil \
+		pamtopam pamtopdbimg pamtopfm pamtopnm pamtosrf pamtouil \
 		pamtowinicon pamtoxvmini \
-		pbmtopgm pfmtopam \
+		pbmtopgm pdbimgtopam pfmtopam \
 	        pgmtopbm pgmtoppm ppmtopgm pnmtoddif \
-		pnmtopclxl \
+		pnmtopclxl pnmtorast \
 		pnmtosgi pnmtosir pamtotga pnmtoxwd \
-		rlatopam sgitopnm sirtopnm sunicontopnm \
+		rasttopnm rlatopam sgitopnm sirtopnm srftopam sunicontopnm \
 		winicontopam xwdtopnm zeisstopnm
 
-BINARIES = \
-  $(PORTBINARIES) \
-  pamtopdbimg \
-  pamtosrf \
-  pdbimgtopam \
-  pnmtorast \
-  rasttopnm \
-  srftopam \
-
 ifneq ($(DONT_HAVE_PROCESS_MGMT),Y)
-  PORTBINARIES += pstopnm
-  BINARIES += pnmtops
+  PORTBINARIES += pstopnm pnmtops
 endif
 
 ifeq ($(HAVE_PNGLIB),Y)
-  BINARIES += pnmtopng pngtopam pamrgbatopng
+  PORTBINARIES += pnmtopng pngtopam pamrgbatopng
 endif
 ifneq ($(JPEGLIB),NONE)
-  BINARIES += jpegtopnm pnmtojpeg
+  PORTBINARIES += jpegtopnm pnmtojpeg
 endif
 ifneq ($(TIFF_PREREQ_MISSING),Y)
-  BINARIES += tifftopnm pamtotiff pnmtotiffcmyk
+  PORTBINARIES += tifftopnm pamtotiff pnmtotiffcmyk
 endif
 ifneq ($(URTLIB),NONE)
-  BINARIES += rletopnm pnmtorle
+  PORTBINARIES += rletopnm pnmtorle
 endif
 
 ifneq ($(XML2_LIBS),NONE)
-  BINARIES += svgtopam
+  PORTBINARIES += svgtopam
 endif 
 
+BINARIES = $(PORTBINARIES)
+
 MERGEBINARIES = $(BINARIES)
 
 EXTRA_OBJECTS = exif.o rast.o ipdb.o srf.o
@@ -189,12 +181,14 @@ else
   LIBOPTR =
 endif
 
-LIBOPTS_TIFF = $(shell $(LIBOPT) $(NETPBMLIB) \
+LIBOPTS_TIFF = $(shell $(LIBOPT) \
   $(LIBOPTR) $(TIFFLIB) $(TIFFLIB_EXTRALIBS))
 
-tifftopnm pamtotiff pnmtotiffcmyk: %: %.o tiff.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o tiff.o \
-	  $(LIBOPTS_TIFF) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
+tifftopnm pamtotiff pnmtotiffcmyk: tiff.o
+tifftopnm pamtotiff pnmtotiffcmyk: ADDL_OBJECTS = tiff.o
+tifftopnm pamtotiff pnmtotiffcmyk: \
+  LDFLAGS_TARGET = \
+ $(shell $(LIBOPT)  $(LIBOPTR) $(TIFFLIB) $(TIFFLIB_EXTRALIBS))
 
 ifneq ($(shell $(TEST_PKGCONFIG_LIBPNG)),)
   # pkg-config libpng works on this system
@@ -209,66 +203,44 @@ else
   endif
 endif
 
-pngtopam: %: %.o pngx.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o pngx.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB)) \
-	  $(PNGLIB_LIBOPTS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-pnmtopng: %: %.o pngx.o pngtxt.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o pngx.o pngtxt.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB)) \
-	  $(PNGLIB_LIBOPTS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-pamrgbatopng: %: %.o pngx.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o pngx.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB)) $(PNGLIB_LIBOPTS) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-jpegtopnm: %: %.o jpegdatasource.o exif.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $< jpegdatasource.o exif.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIB)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) 
-
-pnmtojpeg: %: %.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIB)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-srftopam pamtosrf: %: %.o srf.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o srf.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-svgtopam: %: %.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR)) \
-	  $(XML2_LIBS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
+pngtopam: pngx.o
+pngtopam: ADDL_OBJECTS = pngx.o
+pngtopam: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS)
+
+pnmtopng: pngx.o pngtxt.o
+pnmtopng: ADDL_OBJECTS = pngx.o pngtxt.o
+pnmtopng: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS)
+
+pamrgbatopng: pngx.o
+pamrgbatopng: ADDL_OBJECTS = pngx.o
+pamrgbatopng: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS)
+
+jpegtopnm: jpegdatasource.o exif.o
+jpegtopnm: ADDL_OBJECTS = jpegdatasource.o exif.o
+jpegtopnm: LDFLAGS_TARGET = $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIB))
+
+srftopam pamtosrf: srf.o
+srftopam pamtosrf: ADDL_OBJECTS = srf.o
+
+pnmtojpeg: LDFLAGS_TARGET = $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIB))
+
+svgtopam: LDFLAGS_TARGET = $(XML2_LIBS)
 
 # If URTLIB is BUNDLED_URTLIB, then we're responsible for building it, which
 # means it needs to be a dependency:
 ifeq ($(URTLIB), $(BUNDLED_URTLIB))
-  URTLIBDEP = $(URTLIB)
+rletopnm pnmtorle: $(URTLIB)
 endif
 
-rletopnm pnmtorle: %: %.o $(NETPBMLIB) $(URTLIBDEP) $(LIBOPT)
-	$(LD) -o $@ $@.o \
-	  $(shell $(LIBOPT) $(URTLIB) $(NETPBMLIB)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-pnmtops: %: %.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB) $(PNMTOPS_ZLIB_OPT)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-pnmtorast rasttopnm: %: %.o rast.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o rast.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-pdbimgtopam pamtopdbimg: %: %.o ipdb.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $@.o ipdb.o \
-	  $(shell $(LIBOPT) $(NETPBMLIB)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
+rletopnm pnmtorle: LDFLAGS_TARGET = $(shell $(LIBOPT) $(URTLIB))
+
+pnmtops: LDFLAGS_TARGET = $(shell $(LIBOPT) $(PNMTOPS_ZLIB_OPT))
+
+pnmtorast rasttopnm: rast.o
+pnmtorast rasttopnm: ADDL_OBJECTS = rast.o
+
+pdbimgtopam pamtopdbimg: ipdb.o
+pdbimgtopam pamtopdbimg: ADDL_OBJECTS = ipdb.o
 
 bmptopnm.o bmptopnm.o2: bmp.h
 
diff --git a/converter/other/cameratopam/Makefile b/converter/other/cameratopam/Makefile
index 4470d472..11ca4e1d 100644
--- a/converter/other/cameratopam/Makefile
+++ b/converter/other/cameratopam/Makefile
@@ -19,22 +19,20 @@ include $(BUILDDIR)/config.mk
 .PHONY: all
 all: cameratopam
 
-OBJECTS = util.o identify.o cameratopam.o camera.o foveon.o decode.o \
+ADDL_OBJECTS = util.o identify.o camera.o foveon.o decode.o \
 	canon.o ljpeg.o dng.o
 
+OBJECTS = cameratopam.o $(ADDL_OBJECTS)
+
 camera.o camera.o2: CFLAGS_TARGET = $(HAVE_JPEG_DEFINE)
 
 MERGE_OBJECTS =
 
-BINARIES = cameratopam
+PORTBINARIES = cameratopam
+BINARIES = $(PORTBINARIES)
 MERGEBINARIES = 
 SCRIPTS = 
 
 include $(SRCDIR)/common.mk
 
-cameratopam: $(OBJECTS) $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ \
-          $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) \
-	  $(RPATH) $(LADD)
-
+cameratopam: $(ADDL_OBJECTS)
diff --git a/converter/other/exif.c b/converter/other/exif.c
index 87d89bd7..1bfe4b2b 100644
--- a/converter/other/exif.c
+++ b/converter/other/exif.c
@@ -46,22 +46,21 @@
 
 #include "exif.h"
 
-static unsigned char * LastExifRefd;
-static unsigned char * DirWithThumbnailPtrs;
+static const unsigned char * DirWithThumbnailPtrs;
 static double FocalplaneXRes;
 bool HaveXRes;
 static double FocalplaneUnits;
 static int ExifImageWidth;
-static int MotorolaOrder = 0;
 
 typedef struct {
     unsigned short Tag;
     const char * Desc;
-}TagTable_t;
+} TagTable;
+
 
 
 /* Describes format descriptor */
-static int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
+static int const bytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
 #define NUM_FORMATS 12
 
 #define FMT_BYTE       1 
@@ -120,7 +119,7 @@ static int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
 #define TAG_THUMBNAIL_OFFSET  0x0201
 #define TAG_THUMBNAIL_LENGTH  0x0202
 
-static TagTable_t const TagTable[] = {
+static TagTable const tagTable[] = {
   {   0x100,   "ImageWidth"},
   {   0x101,   "ImageLength"},
   {   0x102,   "BitsPerSample"},
@@ -208,498 +207,583 @@ static TagTable_t const TagTable[] = {
 
 
 
+typedef enum { NORMAL, MOTOROLA } ByteOrder;
+
+
+
+static uint16_t
+get16u(const void * const data,
+       ByteOrder    const byteOrder) {
 /*--------------------------------------------------------------------------
    Convert a 16 bit unsigned value from file's native byte order
 --------------------------------------------------------------------------*/
-static int Get16u(void * Short)
-{
-    if (MotorolaOrder){
-        return (((unsigned char *)Short)[0] << 8) | 
-            ((unsigned char *)Short)[1];
+    if (byteOrder == MOTOROLA){
+        return (((const unsigned char *)data)[0] << 8) | 
+            ((const unsigned char *)data)[1];
     }else{
-        return (((unsigned char *)Short)[1] << 8) | 
-            ((unsigned char *)Short)[0];
+        return (((const unsigned char *)data)[1] << 8) | 
+            ((const unsigned char *)data)[0];
     }
 }
 
+
+
+static int32_t
+get32s(const void * const data,
+       ByteOrder    const byteOrder) {
 /*--------------------------------------------------------------------------
    Convert a 32 bit signed value from file's native byte order
 --------------------------------------------------------------------------*/
-static int Get32s(void * Long)
-{
-    if (MotorolaOrder){
+    if (byteOrder == MOTOROLA){
         return  
-            ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16) |
-            (((unsigned char *)Long)[2] << 8 ) | 
-            (((unsigned char *)Long)[3] << 0 );
-    }else{
+            (((const char *)data)[0] << 24) |
+            (((const unsigned char *)data)[1] << 16) |
+            (((const unsigned char *)data)[2] << 8 ) | 
+            (((const unsigned char *)data)[3] << 0 );
+    } else {
         return  
-            ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16) |
-            (((unsigned char *)Long)[1] << 8 ) | 
-            (((unsigned char *)Long)[0] << 0 );
+            (((const char *)data)[3] << 24) |
+            (((const unsigned char *)data)[2] << 16) |
+            (((const unsigned char *)data)[1] << 8 ) | 
+            (((const unsigned char *)data)[0] << 0 );
     }
 }
 
+
+
+static uint32_t
+get32u(const void * const data,
+       ByteOrder    const byteOrder) {
 /*--------------------------------------------------------------------------
    Convert a 32 bit unsigned value from file's native byte order
 --------------------------------------------------------------------------*/
-static unsigned Get32u(void * Long)
-{
-    return (unsigned)Get32s(Long) & 0xffffffff;
+    return (uint32_t)get32s(data, byteOrder) & 0xffffffff;
 }
 
+
+
+static void
+printFormatNumber(FILE *       const fileP, 
+                  const void * const ValuePtr, 
+                  int          const Format,
+                  int          const ByteCount,
+                  ByteOrder    const byteOrder) {
 /*--------------------------------------------------------------------------
    Display a number as one of its many formats
 --------------------------------------------------------------------------*/
-static void PrintFormatNumber(FILE * const file, 
-                              void * const ValuePtr, 
-                              int const Format, int const ByteCount)
-{
     switch(Format){
     case FMT_SBYTE:
-    case FMT_BYTE:      printf("%02x\n",*(unsigned char *)ValuePtr); break;
-    case FMT_USHORT:    fprintf(file, "%d\n",Get16u(ValuePtr));    break;
+    case FMT_BYTE:
+        fprintf(fileP, "%02x\n", *(unsigned char *)ValuePtr);
+        break;
+    case FMT_USHORT:
+        fprintf(fileP, "%d\n",get16u(ValuePtr, byteOrder));
+        break;
     case FMT_ULONG:     
-    case FMT_SLONG:     fprintf(file, "%d\n",Get32s(ValuePtr));    break;
+    case FMT_SLONG:
+        fprintf(fileP, "%d\n",get32s(ValuePtr, byteOrder));
+        break;
     case FMT_SSHORT:    
-        fprintf(file, "%hd\n",(signed short)Get16u(ValuePtr));     break;
+        fprintf(fileP, "%hd\n",(signed short)get16u(ValuePtr, byteOrder));
+        break;
     case FMT_URATIONAL:
     case FMT_SRATIONAL: 
-        fprintf(file, "%d/%d\n",Get32s(ValuePtr), Get32s(4+(char *)ValuePtr));
+        fprintf(fileP, "%d/%d\n",get32s(ValuePtr, byteOrder),
+                get32s(4+(char *)ValuePtr, byteOrder));
         break;
     case FMT_SINGLE:    
-        fprintf(file, "%f\n",(double)*(float *)ValuePtr);          break;
-    case FMT_DOUBLE:    fprintf(file, "%f\n",*(double *)ValuePtr); break;
+        fprintf(fileP, "%f\n",(double)*(float *)ValuePtr);
+        break;
+    case FMT_DOUBLE:
+        fprintf(fileP, "%f\n",*(double *)ValuePtr);
+        break;
     default: 
-        fprintf(file, "Unknown format %d:", Format);
+        fprintf(fileP, "Unknown format %d:", Format);
         {
-            int a;
-            for (a=0; a < ByteCount && a < 16; ++a)
+            unsigned int a;
+            for (a = 0; a < ByteCount && a < 16; ++a)
                 printf("%02x", ((unsigned char *)ValuePtr)[a]);
         }
-        fprintf(file, "\n");
+        fprintf(fileP, "\n");
     }
 }
 
 
+
+static double
+convertAnyFormat(const void * const ValuePtr,
+                 int          const Format,
+                 ByteOrder    const byteOrder) {
 /*--------------------------------------------------------------------------
    Evaluate number, be it int, rational, or float from directory.
 --------------------------------------------------------------------------*/
-static double ConvertAnyFormat(void * ValuePtr, int Format)
-{
     double Value;
     Value = 0;
 
     switch(Format){
-        case FMT_SBYTE:     Value = *(signed char *)ValuePtr;  break;
-        case FMT_BYTE:      Value = *(unsigned char *)ValuePtr;        break;
-
-        case FMT_USHORT:    Value = Get16u(ValuePtr);          break;
-        case FMT_ULONG:     Value = Get32u(ValuePtr);          break;
-
-        case FMT_URATIONAL:
-        case FMT_SRATIONAL: 
-            {
-                int Num,Den;
-                Num = Get32s(ValuePtr);
-                Den = Get32s(4+(char *)ValuePtr);
-                if (Den == 0){
-                    Value = 0;
-                }else{
-                    Value = (double)Num/Den;
-                }
-                break;
-            }
-
-        case FMT_SSHORT:    Value = (signed short)Get16u(ValuePtr);  break;
-        case FMT_SLONG:     Value = Get32s(ValuePtr);                break;
+    case FMT_SBYTE:
+        Value = *(signed char *)ValuePtr;
+        break;
+    case FMT_BYTE:
+        Value = *(unsigned char *)ValuePtr;
+        break;
+    case FMT_USHORT:
+        Value = get16u(ValuePtr, byteOrder);
+        break;
+    case FMT_ULONG:
+        Value = get32u(ValuePtr, byteOrder);
+        break;
+    case FMT_URATIONAL:
+    case FMT_SRATIONAL: {
+        int num, den;
+        num = get32s(ValuePtr, byteOrder);
+        den = get32s(4+(char *)ValuePtr, byteOrder);
+        Value = den == 0 ? 0 : (double)(num/den);
+    } break;
+    case FMT_SSHORT:
+        Value = (signed short)get16u(ValuePtr, byteOrder);
+        break;
+    case FMT_SLONG:
+        Value = get32s(ValuePtr, byteOrder);
+        break;
 
-        /* Not sure if this is correct (never seen float used in Exif format)
-         */
-        case FMT_SINGLE:    Value = (double)*(float *)ValuePtr;      break;
-        case FMT_DOUBLE:    Value = *(double *)ValuePtr;             break;
+    /* Not sure if this is correct (never seen float used in Exif format) */
+    case FMT_SINGLE:
+        Value = (double)*(float *)ValuePtr;
+        break;
+    case FMT_DOUBLE:
+        Value = *(double *)ValuePtr;
+        break;
     }
     return Value;
 }
 
-/*--------------------------------------------------------------------------
-   Process one of the nested EXIF directories.
---------------------------------------------------------------------------*/
-static void 
-ProcessExifDir(unsigned char *  const ExifData, 
-               unsigned int     const ExifLength,
-               unsigned int     const DirOffset,
-               ImageInfo_t *    const ImageInfoP, 
-               int              const ShowTags,
-               unsigned char ** const LastExifRefdP) {
-
-    unsigned char * const DirStart = ExifData + DirOffset;
-    int de;
-    int a;
-    int NumDirEntries;
-    unsigned ThumbnailOffset = 0;
-    unsigned ThumbnailSize = 0;
-
-    NumDirEntries = Get16u(DirStart);
-    #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
 
-    {
-        unsigned char * DirEnd;
-        DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
-        if (DirEnd+4 > (ExifData+ExifLength)){
-            if (DirEnd+2 == ExifData+ExifLength || 
-                DirEnd == ExifData+ExifLength){
-                /* Version 1.3 of jhead would truncate a bit too much.
-                   This also caught later on as well.
-                */
-            }else{
-                /* Note: Files that had thumbnails trimmed with jhead
-                   1.3 or earlier might trigger this.
+
+static void
+traceTag(int                   const tag,
+         int                   const format,
+         const unsigned char * const valuePtr,
+         unsigned int          const byteCount,
+         ByteOrder             const byteOrder) {
+             
+    /* Show tag name */
+    unsigned int a;
+    bool found;
+    for (a = 0, found = false; !found; ++a){
+        if (tagTable[a].Tag == 0){
+            fprintf(stderr, "  Unknown Tag %04x Value = ", tag);
+            found = true;
+        }
+        if (tagTable[a].Tag == tag){
+            fprintf(stderr, "    %s = ",tagTable[a].Desc);
+            found = true;
+        }
+    }
+
+    /* Show tag value. */
+    switch(format){
+
+    case FMT_UNDEFINED:
+        /* Undefined is typically an ascii string. */
+
+    case FMT_STRING: {
+        /* String arrays printed without function call
+           (different from int arrays)
+        */
+        bool noPrint;
+        printf("\"");
+        for (a = 0, noPrint = false; a < byteCount; ++a){
+            if (ISPRINT((valuePtr)[a])){
+                fprintf(stderr, "%c", valuePtr[a]);
+                noPrint = false;
+            } else {
+                /* Avoiding indicating too many unprintable characters of
+                   proprietary bits of binary information this program may not
+                   know how to parse.
                 */
-                pm_message("Illegal directory entry size");
-                return;
+                if (!noPrint){
+                    fprintf(stderr, "?");
+                    noPrint = true;
+                }
             }
         }
-        if (DirEnd > LastExifRefd) LastExifRefd = DirEnd;
+        fprintf(stderr, "\"\n");
+    } break;
+
+    default:
+        /* Handle arrays of numbers later (will there ever be?)*/
+        printFormatNumber(stderr, valuePtr, format, byteCount, byteOrder);
     }
+}
+
+
+
+/* Forward declaration for recursion */
+
+static void 
+processExifDir(const unsigned char *  const ExifData, 
+               unsigned int           const ExifLength,
+               unsigned int           const DirOffset,
+               exif_ImageInfo *       const imageInfoP, 
+               ByteOrder              const byteOrder,
+               bool                   const wantTagTrace,
+               const unsigned char ** const LastExifRefdP);
+
+
+static void
+processDirEntry(const unsigned char *  const dirEntry,
+                const unsigned char *  const exifData,
+                unsigned int           const exifLength,
+                ByteOrder              const byteOrder,
+                bool                   const wantTagTrace,
+                exif_ImageInfo *       const imageInfoP, 
+                unsigned int *         const thumbnailOffsetP,
+                unsigned int *         const thumbnailSizeP,
+                bool *                 const haveThumbnailP,
+                const unsigned char ** const lastExifRefdP) {
+
+    int const tag        = get16u(&dirEntry[0], byteOrder);
+    int const format     = get16u(&dirEntry[2], byteOrder);
+    int const components = get32u(&dirEntry[4], byteOrder);
+
+    const unsigned char * valuePtr;
+        /* This actually can point to a variety of things; it must be cast to
+           other types when used.  But we use it as a byte-by-byte cursor, so
+           we declare it as a pointer to a generic byte here.
+        */
+    unsigned int byteCount;
 
-    if (ShowTags){
-        pm_message("Directory with %d entries",NumDirEntries);
+    if ((format-1) >= NUM_FORMATS) {
+        /* (-1) catches illegal zero case as unsigned underflows
+           to positive large.  
+        */
+        pm_message("Illegal number format %d for tag %04x", format, tag);
+        return;
+    }
+        
+    byteCount = components * bytesPerFormat[format];
+
+    if (byteCount > 4){
+        unsigned const offsetVal = get32u(&dirEntry[8], byteOrder);
+        /* If its bigger than 4 bytes, the dir entry contains an offset.*/
+        if (offsetVal + byteCount > exifLength){
+            /* Bogus pointer offset and / or bytecount value */
+            pm_message("Illegal pointer offset value in EXIF "
+                       "for tag %04x.  "
+                       "Offset %d bytes %d ExifLen %d\n",
+                       tag, offsetVal, byteCount, exifLength);
+            return;
+        }
+        valuePtr = &exifData[offsetVal];
+    } else {
+        /* 4 bytes or less and value is in the dir entry itself */
+        valuePtr = &dirEntry[8];
     }
 
-    for (de=0;de<NumDirEntries;de++){
-        int Tag, Format, Components;
-        unsigned char * ValuePtr;
-            /* This actually can point to a variety of things; it must
-               be cast to other types when used.  But we use it as a
-               byte-by-byte cursor, so we declare it as a pointer to a
-               generic byte here.  
-            */
-        int ByteCount;
-        unsigned char * DirEntry;
-        DirEntry = DIR_ENTRY_ADDR(DirStart, de);
+    if (*lastExifRefdP < valuePtr + byteCount){
+        /* Keep track of last byte in the exif header that was actually
+           referenced.  That way, we know where the discardable thumbnail data
+           begins.
+        */
+        *lastExifRefdP = valuePtr + byteCount;
+    }
 
-        Tag = Get16u(DirEntry);
-        Format = Get16u(DirEntry+2);
-        Components = Get32u(DirEntry+4);
+    if (wantTagTrace)
+        traceTag(tag, format, valuePtr, byteCount, byteOrder);
 
-        if ((Format-1) >= NUM_FORMATS) {
-            /* (-1) catches illegal zero case as unsigned underflows
-               to positive large.  
-            */
-            pm_message("Illegal number format %d for tag %04x", Format, Tag);
-            continue;
+    *haveThumbnailP = (tag == TAG_THUMBNAIL_OFFSET);
+
+    /* Extract useful components of tag */
+    switch (tag){
+
+    case TAG_MAKE:
+        STRSCPY(imageInfoP->CameraMake, (const char*)valuePtr);
+        break;
+
+    case TAG_MODEL:
+        STRSCPY(imageInfoP->CameraModel, (const char*)valuePtr);
+        break;
+
+    case TAG_XRESOLUTION:
+        imageInfoP->XResolution = 
+            convertAnyFormat(valuePtr, format, byteOrder);
+        break;
+
+    case TAG_YRESOLUTION:
+        imageInfoP->YResolution = 
+            convertAnyFormat(valuePtr, format, byteOrder);
+        break;
+
+    case TAG_DATETIME_ORIGINAL:
+        STRSCPY(imageInfoP->DateTime, (const char*)valuePtr);
+        imageInfoP->DatePointer = (const char*)valuePtr;
+        break;
+
+    case TAG_USERCOMMENT: {
+        /* Olympus has this padded with trailing spaces.  We stop the copy
+           where those start.
+        */
+        const char * const value = (const char *)valuePtr;
+
+        unsigned int cursor;
+        unsigned int outCursor;
+        unsigned int end;
+
+        for (end = byteCount; end > 0 && value[end] == ' '; --end);
+
+        /* Skip "ASCII" if it is there */
+        if (end >= 5 && MEMEQ(value, "ASCII", 5))
+            cursor = 5;
+        else
+            cursor = 0;
+
+        /* Skip consecutive blanks and NULs */
+
+        for (;
+             cursor < byteCount && 
+                 (value[cursor] == '\0' || value[cursor] == ' ');
+             ++cursor);
+
+        /* Copy the rest as the comment */
+
+        for (outCursor = 0;
+             cursor < end && outCursor < MAX_COMMENT-1;
+             ++cursor)
+            imageInfoP->Comments[outCursor++] = value[cursor];
+
+        imageInfoP->Comments[outCursor++] = '\0';
+    } break;
+
+    case TAG_FNUMBER:
+        /* Simplest way of expressing aperture, so I trust it the most.
+           (overwrite previously computd value if there is one)
+        */
+        imageInfoP->ApertureFNumber = 
+            (float)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
+
+    case TAG_APERTURE:
+    case TAG_MAXAPERTURE:
+        /* More relevant info always comes earlier, so only use this field if
+           we don't have appropriate aperture information yet.
+        */
+        if (imageInfoP->ApertureFNumber == 0){
+            imageInfoP->ApertureFNumber = (float)
+                exp(convertAnyFormat(valuePtr, format, byteOrder)
+                    * log(2) * 0.5);
         }
-        
-        ByteCount = Components * BytesPerFormat[Format];
-
-        if (ByteCount > 4){
-            unsigned OffsetVal;
-            OffsetVal = Get32u(DirEntry+8);
-            /* If its bigger than 4 bytes, the dir entry contains an offset.*/
-            if (OffsetVal+ByteCount > ExifLength){
-                /* Bogus pointer offset and / or bytecount value */
-                pm_message("Illegal pointer offset value in EXIF "
-                           "for tag %04x.  "
-                           "Offset %d bytes %d ExifLen %d\n",
-                           Tag, OffsetVal, ByteCount, ExifLength);
-                continue;
-            }
-            ValuePtr = ExifData+OffsetVal;
+        break;
+
+    case TAG_FOCALLENGTH:
+        /* Nice digital cameras actually save the focal length
+           as a function of how farthey are zoomed in. 
+        */
+
+        imageInfoP->FocalLength = 
+            (float)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
+
+    case TAG_SUBJECT_DISTANCE:
+        /* Inidcates the distacne the autofocus camera is focused to.
+           Tends to be less accurate as distance increases.
+        */
+        imageInfoP->Distance = 
+            (float)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
+
+    case TAG_EXPOSURETIME:
+        /* Simplest way of expressing exposure time, so I
+           trust it most.  (overwrite previously computd value
+           if there is one) 
+        */
+        imageInfoP->ExposureTime = 
+            (float)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
+
+    case TAG_SHUTTERSPEED:
+        /* More complicated way of expressing exposure time,
+           so only use this value if we don't already have it
+           from somewhere else.  
+        */
+        if (imageInfoP->ExposureTime == 0){
+            imageInfoP->ExposureTime = (float)
+                (1/exp(convertAnyFormat(valuePtr, format, byteOrder)
+                       * log(2)));
+        }
+        break;
+
+    case TAG_FLASH:
+        if ((int)convertAnyFormat(valuePtr, format, byteOrder) & 0x7){
+            imageInfoP->FlashUsed = TRUE;
         }else{
-            /* 4 bytes or less and value is in the dir entry itself */
-            ValuePtr = DirEntry+8;
+            imageInfoP->FlashUsed = FALSE;
         }
+        break;
 
-        if (*LastExifRefdP < ValuePtr+ByteCount){
-            /* Keep track of last byte in the exif header that was
-               actually referenced.  That way, we know where the
-               discardable thumbnail data begins.
-            */
-            *LastExifRefdP = ValuePtr+ByteCount;
+    case TAG_ORIENTATION:
+        imageInfoP->Orientation = 
+            (int)convertAnyFormat(valuePtr, format, byteOrder);
+        if (imageInfoP->Orientation < 1 || 
+            imageInfoP->Orientation > 8){
+            pm_message("Undefined rotation value %d",
+                       imageInfoP->Orientation);
+            imageInfoP->Orientation = 0;
         }
+        break;
 
-        if (ShowTags){
-            /* Show tag name */
-            for (a=0;;a++){
-                if (TagTable[a].Tag == 0){
-                    fprintf(stderr, "  Unknown Tag %04x Value = ", Tag);
-                    break;
-                }
-                if (TagTable[a].Tag == Tag){
-                    fprintf(stderr, "    %s = ",TagTable[a].Desc);
-                    break;
-                }
-            }
+    case TAG_EXIF_IMAGELENGTH:
+    case TAG_EXIF_IMAGEWIDTH:
+        /* Use largest of height and width to deal with images
+           that have been rotated to portrait format.  
+        */
+        ExifImageWidth =
+            MIN(ExifImageWidth,
+                (int)convertAnyFormat(valuePtr, format, byteOrder));
+        break;
 
-            /* Show tag value. */
-            switch(Format){
-
-                case FMT_UNDEFINED:
-                    /* Undefined is typically an ascii string. */
-
-                case FMT_STRING:
-                    /* String arrays printed without function call
-                       (different from int arrays)
-                    */
-                    {
-                        int NoPrint = 0;
-                        printf("\"");
-                        for (a=0;a<ByteCount;a++){
-                            if (ISPRINT((ValuePtr)[a])){
-                                fprintf(stderr, "%c", (ValuePtr)[a]);
-                                NoPrint = 0;
-                            }else{
-
-                                /* Avoiding indicating too many
-                                   unprintable characters of proprietary
-                                   bits of binary information this
-                                   program may not know how to parse.  
-                                */
-                                if (!NoPrint){
-                                    fprintf(stderr, "?");
-                                    NoPrint = 1;
-                                }
-                            }
-                        }
-                        fprintf(stderr, "\"\n");
-                    }
-                    break;
+    case TAG_FOCALPLANEXRES:
+        HaveXRes = TRUE;
+        FocalplaneXRes = convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-                default:
-                    /* Handle arrays of numbers later (will there ever be?)*/
-                    PrintFormatNumber(stderr, ValuePtr, Format, ByteCount);
-            }
+    case TAG_FOCALPLANEUNITS:
+        switch((int)convertAnyFormat(valuePtr, format, byteOrder)){
+        case 1: FocalplaneUnits = 25.4; break; /* 1 inch */
+        case 2: 
+            /* According to the information I was using, 2
+               means meters.  But looking at the Cannon
+               powershot's files, inches is the only
+               sensible value.  
+            */
+            FocalplaneUnits = 25.4;
+            break;
+
+        case 3: FocalplaneUnits = 10;   break;  /* 1 centimeter*/
+        case 4: FocalplaneUnits = 1;    break;  /* 1 millimeter*/
+        case 5: FocalplaneUnits = .001; break;  /* 1 micrometer*/
         }
+        break;
 
-        /* Extract useful components of tag */
-        switch(Tag){
-
-            case TAG_MAKE:
-                STRSCPY(ImageInfoP->CameraMake, (char*)ValuePtr);
-                break;
-
-            case TAG_MODEL:
-                STRSCPY(ImageInfoP->CameraModel, (char*)ValuePtr);
-                break;
-
-            case TAG_XRESOLUTION:
-                ImageInfoP->XResolution = 
-                    ConvertAnyFormat(ValuePtr, Format);
-                break;
-    
-            case TAG_YRESOLUTION:
-                ImageInfoP->YResolution = 
-                    ConvertAnyFormat(ValuePtr, Format);
-                break;
-    
-            case TAG_DATETIME_ORIGINAL:
-                STRSCPY(ImageInfoP->DateTime, (char*)ValuePtr);
-                ImageInfoP->DatePointer = (char*)ValuePtr;
-                break;
-
-            case TAG_USERCOMMENT:
-                /* Olympus has this padded with trailing spaces.
-                   Remove these first. 
-                */
-                for (a=ByteCount;;){
-                    a--;
-                    if (((char*)ValuePtr)[a] == ' '){
-                        ((char*)ValuePtr)[a] = '\0';
-                    }else{
-                        break;
-                    }
-                    if (a == 0) break;
-                }
+        /* Remaining cases contributed by: Volker C. Schoech
+           (schoech@gmx.de)
+        */
 
-                /* Copy the comment */
-                if (memcmp(ValuePtr, "ASCII",5) == 0){
-                    for (a=5;a<10;a++){
-                        char c;
-                        c = ((char*)ValuePtr)[a];
-                        if (c != '\0' && c != ' '){
-                            strncpy(ImageInfoP->Comments, (char*)ValuePtr+a, 
-                                    199);
-                            break;
-                        }
-                    }
-                    
-                }else{
-                    strncpy(ImageInfoP->Comments, (char*)ValuePtr, 199);
-                }
-                break;
-
-            case TAG_FNUMBER:
-                /* Simplest way of expressing aperture, so I trust it the most.
-                   (overwrite previously computd value if there is one)
-                   */
-                ImageInfoP->ApertureFNumber = 
-                    (float)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_APERTURE:
-            case TAG_MAXAPERTURE:
-                /* More relevant info always comes earlier, so only
-                 use this field if we don't have appropriate aperture
-                 information yet. 
-                */
-                if (ImageInfoP->ApertureFNumber == 0){
-                    ImageInfoP->ApertureFNumber = (float)
-                        exp(ConvertAnyFormat(ValuePtr, Format)*log(2)*0.5);
-                }
-                break;
+    case TAG_EXPOSURE_BIAS:
+        imageInfoP->ExposureBias = 
+            (float) convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-            case TAG_FOCALLENGTH:
-                /* Nice digital cameras actually save the focal length
-                   as a function of how farthey are zoomed in. 
-                */
+    case TAG_WHITEBALANCE:
+        imageInfoP->Whitebalance = 
+            (int)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-                ImageInfoP->FocalLength = 
-                    (float)ConvertAnyFormat(ValuePtr, Format);
-                break;
+    case TAG_METERING_MODE:
+        imageInfoP->MeteringMode = 
+            (int)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-            case TAG_SUBJECT_DISTANCE:
-                /* Inidcates the distacne the autofocus camera is focused to.
-                   Tends to be less accurate as distance increases.
-                */
-                ImageInfoP->Distance = 
-                    (float)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_EXPOSURETIME:
-                /* Simplest way of expressing exposure time, so I
-                   trust it most.  (overwrite previously computd value
-                   if there is one) 
-                */
-                ImageInfoP->ExposureTime = 
-                    (float)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_SHUTTERSPEED:
-                /* More complicated way of expressing exposure time,
-                   so only use this value if we don't already have it
-                   from somewhere else.  
-                */
-                if (ImageInfoP->ExposureTime == 0){
-                    ImageInfoP->ExposureTime = (float)
-                        (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2)));
-                }
-                break;
+    case TAG_EXPOSURE_PROGRAM:
+        imageInfoP->ExposureProgram = 
+            (int)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-            case TAG_FLASH:
-                if ((int)ConvertAnyFormat(ValuePtr, Format) & 7){
-                    ImageInfoP->FlashUsed = TRUE;
-                }else{
-                    ImageInfoP->FlashUsed = FALSE;
-                }
-                break;
-
-            case TAG_ORIENTATION:
-                ImageInfoP->Orientation = 
-                    (int)ConvertAnyFormat(ValuePtr, Format);
-                if (ImageInfoP->Orientation < 1 || 
-                    ImageInfoP->Orientation > 8){
-                    pm_message("Undefined rotation value %d", 
-                               ImageInfoP->Orientation);
-                    ImageInfoP->Orientation = 0;
-                }
-                break;
+    case TAG_ISO_EQUIVALENT:
+        imageInfoP->ISOequivalent = 
+            (int)convertAnyFormat(valuePtr, format, byteOrder);
+        if ( imageInfoP->ISOequivalent < 50 ) 
+            imageInfoP->ISOequivalent *= 200;
+        break;
 
-            case TAG_EXIF_IMAGELENGTH:
-            case TAG_EXIF_IMAGEWIDTH:
-                /* Use largest of height and width to deal with images
-                   that have been rotated to portrait format.  
-                */
-                a = (int)ConvertAnyFormat(ValuePtr, Format);
-                if (ExifImageWidth < a) ExifImageWidth = a;
-                break;
-
-            case TAG_FOCALPLANEXRES:
-                HaveXRes = TRUE;
-                FocalplaneXRes = ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_FOCALPLANEUNITS:
-                switch((int)ConvertAnyFormat(ValuePtr, Format)){
-                    case 1: FocalplaneUnits = 25.4; break; /* 1 inch */
-                    case 2: 
-                        /* According to the information I was using, 2
-                           means meters.  But looking at the Cannon
-                           powershot's files, inches is the only
-                           sensible value.  
-                        */
-                        FocalplaneUnits = 25.4;
-                        break;
+    case TAG_COMPRESSION_LEVEL:
+        imageInfoP->CompressionLevel = 
+            (int)convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-                    case 3: FocalplaneUnits = 10;   break;  /* 1 centimeter*/
-                    case 4: FocalplaneUnits = 1;    break;  /* 1 millimeter*/
-                    case 5: FocalplaneUnits = .001; break;  /* 1 micrometer*/
-                }
-                break;
+    case TAG_THUMBNAIL_OFFSET:
+        *thumbnailOffsetP = (unsigned int)
+            convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-                /* Remaining cases contributed by: Volker C. Schoech
-                   (schoech@gmx.de)
-                */
+    case TAG_THUMBNAIL_LENGTH:
+        *thumbnailSizeP = (unsigned int)
+            convertAnyFormat(valuePtr, format, byteOrder);
+        break;
 
-            case TAG_EXPOSURE_BIAS:
-                ImageInfoP->ExposureBias = 
-                    (float) ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_WHITEBALANCE:
-                ImageInfoP->Whitebalance = 
-                    (int)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_METERING_MODE:
-                ImageInfoP->MeteringMode = 
-                    (int)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_EXPOSURE_PROGRAM:
-                ImageInfoP->ExposureProgram = 
-                    (int)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_ISO_EQUIVALENT:
-                ImageInfoP->ISOequivalent = 
-                    (int)ConvertAnyFormat(ValuePtr, Format);
-                if ( ImageInfoP->ISOequivalent < 50 ) 
-                    ImageInfoP->ISOequivalent *= 200;
-                break;
-
-            case TAG_COMPRESSION_LEVEL:
-                ImageInfoP->CompressionLevel = 
-                    (int)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_THUMBNAIL_OFFSET:
-                ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
-                DirWithThumbnailPtrs = DirStart;
-                break;
-
-            case TAG_THUMBNAIL_LENGTH:
-                ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
-                break;
-
-            case TAG_EXIF_OFFSET:
-            case TAG_INTEROP_OFFSET:
-                {
-                    unsigned int const SubdirOffset  = Get32u(ValuePtr);
-                    if (SubdirOffset >= ExifLength)
-                        pm_message("Illegal exif or interop offset "
-                                   "directory link.  Offset is %u, "
-                                   "but Exif data is only %u bytes.",
-                                   SubdirOffset, ExifLength);
-                    else
-                        ProcessExifDir(ExifData, ExifLength, SubdirOffset, 
-                                       ImageInfoP, ShowTags, LastExifRefdP);
-                    continue;
-                }
-        }
+    case TAG_EXIF_OFFSET:
+    case TAG_INTEROP_OFFSET: {
+        unsigned int const subdirOffset = get32u(valuePtr, byteOrder);
+        if (subdirOffset >= exifLength)
+            pm_message("Illegal exif or interop offset "
+                       "directory link.  Offset is %u, "
+                       "but Exif data is only %u bytes.",
+                       subdirOffset, exifLength);
+        else
+            processExifDir(exifData, exifLength, subdirOffset, 
+                           imageInfoP, byteOrder, wantTagTrace,
+                           lastExifRefdP);
+    } break;
+    }
+}
+
+
+
+static void 
+processExifDir(const unsigned char *  const exifData, 
+               unsigned int           const exifLength,
+               unsigned int           const dirOffset,
+               exif_ImageInfo *       const imageInfoP, 
+               ByteOrder              const byteOrder,
+               bool                   const wantTagTrace,
+               const unsigned char ** const lastExifRefdP) {
+/*--------------------------------------------------------------------------
+   Process one of the nested EXIF directories.
+--------------------------------------------------------------------------*/
+    const unsigned char * const dirStart = exifData + dirOffset;
+    unsigned int const numDirEntries = get16u(&dirStart[0], byteOrder);
+    unsigned int de;
+    bool haveThumbnail;
+    unsigned int thumbnailOffset;
+    unsigned int thumbnailSize;
+
+    #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
 
+    {
+        const unsigned char * const dirEnd =
+            DIR_ENTRY_ADDR(dirStart, numDirEntries);
+        if (dirEnd + 4 > (exifData + exifLength)){
+            if (dirEnd + 2 == exifData + exifLength || 
+                dirEnd == exifData + exifLength){
+                /* Version 1.3 of jhead would truncate a bit too much.
+                   This also caught later on as well.
+                */
+            }else{
+                /* Note: Files that had thumbnails trimmed with jhead
+                   1.3 or earlier might trigger this.
+                */
+                pm_message("Illegal directory entry size");
+                return;
+            }
+        }
+        *lastExifRefdP = MAX(*lastExifRefdP, dirEnd);
     }
 
+    if (wantTagTrace)
+        pm_message("Directory with %d entries", numDirEntries);
+
+    haveThumbnail   = false;  /* initial value */
+    thumbnailOffset = 0;      /* initial value */
+    thumbnailSize   = 0;      /* initial value */
+
+    for (de = 0; de < numDirEntries; ++de)
+        processDirEntry(DIR_ENTRY_ADDR(dirStart, de), exifData, exifLength,
+                        byteOrder, wantTagTrace, imageInfoP,
+                        &thumbnailOffset, &thumbnailSize, &haveThumbnail,
+                        lastExifRefdP);
+
+    if (haveThumbnail)
+        DirWithThumbnailPtrs = dirStart;
 
     {
         /* In addition to linking to subdirectories via exif tags,
@@ -707,28 +791,30 @@ ProcessExifDir(unsigned char *  const ExifData,
            of each directory.  This has got to be the result of a
            committee!  
         */
-        if (DIR_ENTRY_ADDR(DirStart, NumDirEntries) + 4 <= 
-            ExifData+ExifLength){
-            unsigned int const SubdirOffset =
-                Get32u(DirStart+2+12*NumDirEntries);
-            if (SubdirOffset){
-                unsigned char * const SubdirStart = ExifData + SubdirOffset;
-                if (SubdirStart > ExifData+ExifLength){
-                    if (SubdirStart < ExifData+ExifLength+20){
+        if (DIR_ENTRY_ADDR(dirStart, numDirEntries) + 4 <= 
+            exifData + exifLength){
+            unsigned int const subdirOffset =
+                get32u(dirStart + 2 + 12*numDirEntries, byteOrder);
+            if (subdirOffset){
+                const unsigned char * const subdirStart =
+                    exifData + subdirOffset;
+                if (subdirStart > exifData + exifLength){
+                    if (subdirStart < exifData + exifLength + 20){
                         /* Jhead 1.3 or earlier would crop the whole directory!
                            As Jhead produces this form of format incorrectness,
                            I'll just let it pass silently.
                         */
-                        if (ShowTags) 
+                        if (wantTagTrace) 
                             printf("Thumbnail removed with "
                                    "Jhead 1.3 or earlier\n");
                     }else{
                         pm_message("Illegal subdirectory link");
                     }
                 }else{
-                    if (SubdirOffset <= ExifLength)
-                        ProcessExifDir(ExifData, ExifLength, SubdirOffset,
-                                       ImageInfoP, ShowTags, LastExifRefdP);
+                    if (subdirOffset <= exifLength)
+                        processExifDir(exifData, exifLength, subdirOffset,
+                                       imageInfoP, byteOrder, wantTagTrace,
+                                       lastExifRefdP);
                 }
             }
         }else{
@@ -736,14 +822,14 @@ ProcessExifDir(unsigned char *  const ExifData,
         }
     }
 
-    if (ThumbnailSize && ThumbnailOffset){
-        if (ThumbnailSize + ThumbnailOffset <= ExifLength){
+    if (thumbnailSize && thumbnailOffset){
+        if (thumbnailSize + thumbnailOffset <= exifLength){
             /* The thumbnail pointer appears to be valid.  Store it. */
-            ImageInfoP->ThumbnailPointer = ExifData + ThumbnailOffset;
-            ImageInfoP->ThumbnailSize = ThumbnailSize;
+            imageInfoP->ThumbnailPointer = exifData + thumbnailOffset;
+            imageInfoP->ThumbnailSize = thumbnailSize;
 
-            if (ShowTags){
-                fprintf(stderr, "Thumbnail size: %d bytes\n",ThumbnailSize);
+            if (wantTagTrace){
+                fprintf(stderr, "Thumbnail size: %u bytes\n", thumbnailSize);
             }
         }
     }
@@ -752,46 +838,46 @@ ProcessExifDir(unsigned char *  const ExifData,
 
 
 void 
-process_EXIF(unsigned char * const ExifData,
-             unsigned int    const length,
-             ImageInfo_t *   const ImageInfoP, 
-             int             const ShowTags,
-             const char **   const errorP) {
+exif_parse(const unsigned char * const exifData,
+           unsigned int          const length,
+           exif_ImageInfo *      const imageInfoP, 
+           bool                  const wantTagTrace,
+           const char **         const errorP) {
 /*--------------------------------------------------------------------------
   Interpret an EXIF APP1 marker
 
-  'ExifData' is the actual Exif data; it does not include the
+  'exifData' is the actual Exif data; it does not include the
   "Exif" identifier and length field that often prefix Exif data.
 
   'length' is the length of the Exif section.
 --------------------------------------------------------------------------*/
+    ByteOrder byteOrder;
     int FirstOffset;
-    unsigned char * LastExifRefd;
+    const unsigned char * lastExifRefd;
 
     *errorP = NULL;  /* initial assumption */
 
-    if (ShowTags){
+    if (wantTagTrace)
         fprintf(stderr, "Exif header %d bytes long\n",length);
-    }
 
-    if (memcmp(ExifData+0,"II",2) == 0) {
-        if (ShowTags) 
+    if (MEMEQ(exifData + 0, "II" , 2)) {
+        if (wantTagTrace) 
             fprintf(stderr, "Exif header in Intel order\n");
-        MotorolaOrder = 0;
+        byteOrder = NORMAL;
     } else {
-        if (memcmp(ExifData+0, "MM", 2) == 0) {
-            if (ShowTags) 
+        if (MEMEQ(exifData + 0, "MM", 2)) {
+            if (wantTagTrace) 
                 fprintf(stderr, "Exif header in Motorola order\n");
-            MotorolaOrder = 1;
+            byteOrder = MOTOROLA;
         } else {
             pm_asprintf(errorP, "Invalid alignment marker in Exif "
                         "data.  First two bytes are '%c%c' (0x%02x%02x) "
                         "instead of 'II' or 'MM'.", 
-                        ExifData[0], ExifData[1], ExifData[0], ExifData[1]);
+                        exifData[0], exifData[1], exifData[0], exifData[1]);
         }
     }
     if (!*errorP) {
-        unsigned short const start = Get16u(ExifData + 2);
+        unsigned short const start = get16u(exifData + 2, byteOrder);
         /* Check the next value for correctness. */
         if (start != 0x002a){
             pm_asprintf(errorP, "Invalid Exif header start.  "
@@ -801,7 +887,7 @@ process_EXIF(unsigned char * const ExifData,
         }
     }
     if (!*errorP) {
-        FirstOffset = Get32u(ExifData + 4);
+        FirstOffset = get32u(exifData + 4, byteOrder);
         if (FirstOffset < 8 || FirstOffset > 16){
             /* I used to ensure this was set to 8 (website I used
                indicated its 8) but PENTAX Optio 230 has it set
@@ -810,51 +896,54 @@ process_EXIF(unsigned char * const ExifData,
             pm_message("Suspicious offset of first IFD value in Exif header");
         }
         
-        ImageInfoP->Comments[0] = '\0';  /* Initial value - null string */
+        imageInfoP->Comments[0] = '\0';  /* Initial value - null string */
         
         HaveXRes = FALSE;  /* Initial assumption */
         FocalplaneUnits = 0;
         ExifImageWidth = 0;
         
-        LastExifRefd = ExifData;
+        lastExifRefd = exifData;
         DirWithThumbnailPtrs = NULL;
         
-        ProcessExifDir(ExifData, length, FirstOffset, 
-                       ImageInfoP, ShowTags, &LastExifRefd);
+        processExifDir(exifData, length, FirstOffset, 
+                       imageInfoP, byteOrder, wantTagTrace, &lastExifRefd);
         
         /* Compute the CCD width, in millimeters. */
         if (HaveXRes){
-            ImageInfoP->HaveCCDWidth = 1;
-            ImageInfoP->CCDWidth = 
+            imageInfoP->HaveCCDWidth = 1;
+            imageInfoP->CCDWidth = 
                     (float)(ExifImageWidth * FocalplaneUnits / FocalplaneXRes);
         } else
-            ImageInfoP->HaveCCDWidth = 0;
+            imageInfoP->HaveCCDWidth = 0;
             
-        if (ShowTags){
+        if (wantTagTrace){
             fprintf(stderr, 
                     "Non-settings part of Exif header: %lu bytes\n",
-                    (unsigned long)(ExifData+length-LastExifRefd));
+                    (unsigned long)(exifData + length - lastExifRefd));
         }
     }
 }
 
+
+
+void 
+exif_showImageInfo(const exif_ImageInfo * const imageInfoP,
+                   FILE *                 const fileP) {
 /*--------------------------------------------------------------------------
    Show the collected image info, displaying camera F-stop and shutter
    speed in a consistent and legible fashion.
 --------------------------------------------------------------------------*/
-void 
-ShowImageInfo(ImageInfo_t * const ImageInfoP)
-{
-    if (ImageInfoP->CameraMake[0]){
-        fprintf(stderr, "Camera make  : %s\n",ImageInfoP->CameraMake);
-        fprintf(stderr, "Camera model : %s\n",ImageInfoP->CameraModel);
+    if (imageInfoP->CameraMake[0]) {
+        fprintf(fileP, "Camera make  : %s\n", imageInfoP->CameraMake);
+        fprintf(fileP, "Camera model : %s\n", imageInfoP->CameraModel);
     }
-    if (ImageInfoP->DateTime[0]){
-        fprintf(stderr, "Date/Time    : %s\n",ImageInfoP->DateTime);
-    }
-    fprintf(stderr, "Resolution   : %f x %f\n",
-            ImageInfoP->XResolution, ImageInfoP->YResolution);
-    if (ImageInfoP->Orientation > 1){
+    if (imageInfoP->DateTime[0])
+        fprintf(fileP, "Date/Time    : %s\n", imageInfoP->DateTime);
+
+    fprintf(fileP, "Resolution   : %f x %f\n",
+            imageInfoP->XResolution, imageInfoP->YResolution);
+
+    if (imageInfoP->Orientation > 1) {
 
         /* Only print orientation if one was supplied, and if its not
            1 (normal orientation)
@@ -891,154 +980,144 @@ ShowImageInfo(ImageInfo_t * const ImageInfoP)
             "rotate 270",       /* rotate 270 to right it. */
         };
 
-        fprintf(stderr, "Orientation  : %s\n", 
-                OrientTab[ImageInfoP->Orientation]);
+        fprintf(fileP, "Orientation  : %s\n", 
+                OrientTab[imageInfoP->Orientation]);
     }
 
-    if (ImageInfoP->IsColor == 0){
-        fprintf(stderr, "Color/bw     : Black and white\n");
-    }
-    if (ImageInfoP->FlashUsed >= 0){
-        fprintf(stderr, "Flash used   : %s\n",
-                ImageInfoP->FlashUsed ? "Yes" :"No");
-    }
-    if (ImageInfoP->FocalLength){
-        fprintf(stderr, "Focal length : %4.1fmm",
-                (double)ImageInfoP->FocalLength);
-        if (ImageInfoP->HaveCCDWidth){
-            fprintf(stderr, "  (35mm equivalent: %dmm)",
+    if (imageInfoP->IsColor == 0)
+        fprintf(fileP, "Color/bw     : Black and white\n");
+
+    if (imageInfoP->FlashUsed >= 0)
+        fprintf(fileP, "Flash used   : %s\n",
+                imageInfoP->FlashUsed ? "Yes" :"No");
+
+    if (imageInfoP->FocalLength) {
+        fprintf(fileP, "Focal length : %4.1fmm",
+                (double)imageInfoP->FocalLength);
+        if (imageInfoP->HaveCCDWidth){
+            fprintf(fileP, "  (35mm equivalent: %dmm)",
                     (int)
-                    (ImageInfoP->FocalLength/ImageInfoP->CCDWidth*36 + 0.5));
+                    (imageInfoP->FocalLength/imageInfoP->CCDWidth*36 + 0.5));
         }
-        fprintf(stderr, "\n");
+        fprintf(fileP, "\n");
     }
 
-    if (ImageInfoP->HaveCCDWidth){
-        fprintf(stderr, "CCD width    : %2.4fmm\n",
-                (double)ImageInfoP->CCDWidth);
-    }
+    if (imageInfoP->HaveCCDWidth)
+        fprintf(fileP, "CCD width    : %2.4fmm\n",
+                (double)imageInfoP->CCDWidth);
 
-    if (ImageInfoP->ExposureTime){ 
-        if (ImageInfoP->ExposureTime < 0.010){
-            fprintf(stderr, 
+    if (imageInfoP->ExposureTime) {
+        if (imageInfoP->ExposureTime < 0.010){
+            fprintf(fileP, 
                     "Exposure time: %6.4f s ",
-                    (double)ImageInfoP->ExposureTime);
+                    (double)imageInfoP->ExposureTime);
         }else{
-            fprintf(stderr, 
+            fprintf(fileP, 
                     "Exposure time: %5.3f s ",
-                    (double)ImageInfoP->ExposureTime);
+                    (double)imageInfoP->ExposureTime);
         }
-        if (ImageInfoP->ExposureTime <= 0.5){
-            fprintf(stderr, " (1/%d)",(int)(0.5 + 1/ImageInfoP->ExposureTime));
+        if (imageInfoP->ExposureTime <= 0.5){
+            fprintf(fileP, " (1/%d)",(int)(0.5 + 1/imageInfoP->ExposureTime));
         }
-        fprintf(stderr, "\n");
+        fprintf(fileP, "\n");
     }
-    if (ImageInfoP->ApertureFNumber){
-        fprintf(stderr, "Aperture     : f/%3.1f\n",
-                (double)ImageInfoP->ApertureFNumber);
+    if (imageInfoP->ApertureFNumber){
+        fprintf(fileP, "Aperture     : f/%3.1f\n",
+                (double)imageInfoP->ApertureFNumber);
     }
-    if (ImageInfoP->Distance){
-        if (ImageInfoP->Distance < 0){
-            fprintf(stderr, "Focus dist.  : Infinite\n");
+    if (imageInfoP->Distance){
+        if (imageInfoP->Distance < 0){
+            fprintf(fileP, "Focus dist.  : Infinite\n");
         }else{
-            fprintf(stderr, "Focus dist.  :%5.2fm\n",
-                    (double)ImageInfoP->Distance);
+            fprintf(fileP, "Focus dist.  :%5.2fm\n",
+                    (double)imageInfoP->Distance);
         }
     }
 
-
-
-
-
-    if (ImageInfoP->ISOequivalent){ /* 05-jan-2001 vcs */
-        fprintf(stderr, "ISO equiv.   : %2d\n",(int)ImageInfoP->ISOequivalent);
+    if (imageInfoP->ISOequivalent){ /* 05-jan-2001 vcs */
+        fprintf(fileP, "ISO equiv.   : %2d\n",(int)imageInfoP->ISOequivalent);
     }
-    if (ImageInfoP->ExposureBias){ /* 05-jan-2001 vcs */
-        fprintf(stderr, "Exposure bias:%4.2f\n",
-                (double)ImageInfoP->ExposureBias);
+    if (imageInfoP->ExposureBias){ /* 05-jan-2001 vcs */
+        fprintf(fileP, "Exposure bias:%4.2f\n",
+                (double)imageInfoP->ExposureBias);
     }
         
-    if (ImageInfoP->Whitebalance){ /* 05-jan-2001 vcs */
-        switch(ImageInfoP->Whitebalance) {
+    if (imageInfoP->Whitebalance){ /* 05-jan-2001 vcs */
+        switch(imageInfoP->Whitebalance) {
         case 1:
-            fprintf(stderr, "Whitebalance : sunny\n");
+            fprintf(fileP, "Whitebalance : sunny\n");
             break;
         case 2:
-            fprintf(stderr, "Whitebalance : fluorescent\n");
+            fprintf(fileP, "Whitebalance : fluorescent\n");
             break;
         case 3:
-            fprintf(stderr, "Whitebalance : incandescent\n");
+            fprintf(fileP, "Whitebalance : incandescent\n");
             break;
         default:
-            fprintf(stderr, "Whitebalance : cloudy\n");
+            fprintf(fileP, "Whitebalance : cloudy\n");
         }
     }
-    if (ImageInfoP->MeteringMode){ /* 05-jan-2001 vcs */
-        switch(ImageInfoP->MeteringMode) {
+    if (imageInfoP->MeteringMode){ /* 05-jan-2001 vcs */
+        switch(imageInfoP->MeteringMode) {
         case 2:
-            fprintf(stderr, "Metering Mode: center weight\n");
+            fprintf(fileP, "Metering Mode: center weight\n");
             break;
         case 3:
-            fprintf(stderr, "Metering Mode: spot\n");
+            fprintf(fileP, "Metering Mode: spot\n");
             break;
         case 5:
-            fprintf(stderr, "Metering Mode: matrix\n");
+            fprintf(fileP, "Metering Mode: matrix\n");
             break;
         }
     }
-    if (ImageInfoP->ExposureProgram){ /* 05-jan-2001 vcs */
-        switch(ImageInfoP->ExposureProgram) {
+    if (imageInfoP->ExposureProgram){ /* 05-jan-2001 vcs */
+        switch(imageInfoP->ExposureProgram) {
         case 2:
-            fprintf(stderr, "Exposure     : program (auto)\n");
+            fprintf(fileP, "Exposure     : program (auto)\n");
             break;
         case 3:
-            fprintf(stderr, "Exposure     : aperture priority (semi-auto)\n");
+            fprintf(fileP, "Exposure     : aperture priority (semi-auto)\n");
             break;
         case 4:
-            fprintf(stderr, "Exposure     : shutter priority (semi-auto)\n");
+            fprintf(fileP, "Exposure     : shutter priority (semi-auto)\n");
             break;
         }
     }
-    if (ImageInfoP->CompressionLevel){ /* 05-jan-2001 vcs */
-        switch(ImageInfoP->CompressionLevel) {
+    if (imageInfoP->CompressionLevel){ /* 05-jan-2001 vcs */
+        switch(imageInfoP->CompressionLevel) {
         case 1:
-            fprintf(stderr, "Jpeg Quality  : basic\n");
+            fprintf(fileP, "Jpeg Quality  : basic\n");
             break;
         case 2:
-            fprintf(stderr, "Jpeg Quality  : normal\n");
+            fprintf(fileP, "Jpeg Quality  : normal\n");
             break;
         case 4:
-            fprintf(stderr, "Jpeg Quality  : fine\n");
+            fprintf(fileP, "Jpeg Quality  : fine\n");
             break;
        }
     }
 
-         
-
     /* Print the comment. Print 'Comment:' for each new line of comment. */
-    if (ImageInfoP->Comments[0]){
-        int a,c;
-        fprintf(stderr, "Comment      : ");
-        for (a=0;a<MAX_COMMENT;a++){
-            c = ImageInfoP->Comments[a];
-            if (c == '\0') break;
+    if (imageInfoP->Comments[0]) {
+        unsigned int a;
+
+        fprintf(fileP, "Comment      : ");
+
+        for (a = 0; a < MAX_COMMENT && imageInfoP->Comments[a]; ++a) {
+            char const c = imageInfoP->Comments[a];
             if (c == '\n'){
                 /* Do not start a new line if the string ends with a cr */
-                if (ImageInfoP->Comments[a+1] != '\0'){
-                    fprintf(stderr, "\nComment      : ");
-                }else{
-                    fprintf(stderr, "\n");
-                }
-            }else{
-                putc(c, stderr);
-            }
+                if (imageInfoP->Comments[a+1] != '\0')
+                    fprintf(fileP, "\nComment      : ");
+                else
+                    fprintf(fileP, "\n");
+            } else
+                putc(c, fileP);
         }
-        fprintf(stderr, "\n");
+        fprintf(fileP, "\n");
     }
 
-    fprintf(stderr, "\n");
+    fprintf(fileP, "\n");
 }
 
 
-
-
diff --git a/converter/other/exif.h b/converter/other/exif.h
index 490e08ed..57eb745b 100644
--- a/converter/other/exif.h
+++ b/converter/other/exif.h
@@ -1,6 +1,9 @@
 #ifndef EXIF_H_INCLUDED
 #define EXIF_H_INCLUDED
 
+#include <stdio.h>
+#include "netpbm/pm_c_util.h"
+
 #define MAX_COMMENT 2000
 
 #if MSVCRT
@@ -35,23 +38,24 @@ typedef struct {
     int   CompressionLevel;
     char  Comments[MAX_COMMENT];
 
-    unsigned char * ThumbnailPointer;  /* Pointer at the thumbnail */
+    const unsigned char * ThumbnailPointer;  /* Pointer at the thumbnail */
     unsigned ThumbnailSize;     /* Size of thumbnail. */
 
-    char * DatePointer;
-}ImageInfo_t;
+    const char * DatePointer;
+} exif_ImageInfo;
 
 
 /* Prototypes for exif.c functions. */
 
 void 
-process_EXIF(unsigned char * const ExifSection, 
-             unsigned int    const length,
-             ImageInfo_t *   const ImageInfoP, 
-             int             const ShowTags,
-             const char **   const errorP);
+exif_parse(const unsigned char * const exifSection, 
+           unsigned int          const length,
+           exif_ImageInfo *      const imageInfoP, 
+           bool                  const wantTagTrace,
+           const char **         const errorP);
 
 void 
-ShowImageInfo(ImageInfo_t * const ImageInfoP);
+exif_showImageInfo(const exif_ImageInfo * const imageInfoP,
+                   FILE *                 const fileP);
 
 #endif
diff --git a/converter/other/fiasco/Makefile b/converter/other/fiasco/Makefile
index 16221d77..392e843c 100644
--- a/converter/other/fiasco/Makefile
+++ b/converter/other/fiasco/Makefile
@@ -11,8 +11,9 @@ COMP_INCLUDES = \
 	-I$(SRCDIR)/$(SUBDIR)/codec -I$(SRCDIR)/$(SUBDIR)/input \
 	-I$(SRCDIR)/$(SUBDIR)/output -I$(SRCDIR)/$(SUBDIR)/lib \
 
-BINARIES = pnmtofiasco fiascotopnm
+PORTBINARIES = pnmtofiasco fiascotopnm
 
+BINARIES = $(PORTBINARIES)
 MERGEBINARIES = $(BINARIES)
 
 SCRIPTS =
@@ -24,21 +25,18 @@ FIASCOLIBS = codec/libfiasco_codec.a \
 	     output/libfiasco_output.a \
 	     lib/libfiasco_lib.a 
 
-COMMON_OBJECTS = binerror.o getopt.o getopt1.o params.o
+ADDL_OBJECTS = binerror.o getopt.o getopt1.o params.o
 
-OBJECTS = $(BINARIES:%=%.o) $(COMMON_OBJECTS)
+OBJECTS = $(BINARIES:%=%.o) $(ADDL_OBJECTS)
 
-MERGE_OBJECTS = $(BINARIES:%=%.o2) $(COMMON_OBJECTS)  $(FIASCOLIBS)
+MERGE_OBJECTS = $(BINARIES:%=%.o2) $(ADDL_OBJECTS) $(FIASCOLIBS)
 
 SUBDIRS = codec input output lib
 
 include $(SRCDIR)/common.mk
 
-$(BINARIES):%:%.o $(COMMON_OBJECTS) $(FIASCOLIBS) $(NETPBMLIB) \
-   $(LIBOPT)
-	$(LD) -o $@ $< $(COMMON_OBJECTS) \
-	$(shell $(LIBOPT) $(FIASCOLIBS) $(NETPBMLIB)) $(MATHLIB) \
-	$(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
+$(BINARIES):%:%.o $(ADDL_OBJECTS) $(FIASCOLIBS)
+$(BINARIES): LDFLAGS_TARGET = $(shell $(LIBOPT) $(FIASCOLIBS))
 
 codec/libfiasco_codec.a: $(BUILDDIR)/$(SUBDIR)/codec FORCE
 	$(MAKE) -C codec -f $(SRCDIR)/$(SUBDIR)/codec/Makefile \
diff --git a/converter/other/fiasco/codec/ip.c b/converter/other/fiasco/codec/ip.c
index caa97baf..ade0d916 100644
--- a/converter/other/fiasco/codec/ip.c
+++ b/converter/other/fiasco/codec/ip.c
@@ -282,7 +282,7 @@ standard_ip_image_state (unsigned address, unsigned level, unsigned domain,
    real_t   ip = 0, *imageptr, *stateptr;
 
    if (level > c->options.images_level)
-      error ("Level %d not supported.", level);
+      error ("We cannot interpret a Level %d image.", level);
    
    imageptr = &c->pixels [address * size_of_level (level)];
 
@@ -311,7 +311,7 @@ standard_ip_state_state (unsigned domain1, unsigned domain2, unsigned level,
    real_t   ip = 0, *state1ptr, *state2ptr;
 
    if (level > c->options.images_level)
-      error ("Level %d not supported.", level);
+      error ("We cannot interpret and image with Level %d.", level);
 
    state1ptr = c->images_of_state [domain1] + address_of_level (level);
    state2ptr = c->images_of_state [domain2] + address_of_level (level);
diff --git a/converter/other/fiasco/codec/tiling.c b/converter/other/fiasco/codec/tiling.c
index 89fe3111..21e4428a 100644
--- a/converter/other/fiasco/codec/tiling.c
+++ b/converter/other/fiasco/codec/tiling.c
@@ -224,7 +224,7 @@ perform_tiling (const image_t *image, tiling_t *tiling)
       }
       else
       {
-	 warning ("Unsupported image tiling method.\n"
+	 warning ("We do not know the tiling method.\n"
 		  "Skipping image tiling step.");
 	 tiling->exponent = 0;
       }
diff --git a/converter/other/fiasco/codec/wfa.h b/converter/other/fiasco/codec/wfa.h
index 0b96ba8c..9253affd 100644
--- a/converter/other/fiasco/codec/wfa.h
+++ b/converter/other/fiasco/codec/wfa.h
@@ -19,7 +19,7 @@
 
 #define MAXEDGES  5
 #define MAXSTATES 6000
-#define MAXLABELS 2			/* only bintree supported anymore */
+#define MAXLABELS 2			/* only bintree possible anymore */
 #define MAXLEVEL  22 
 
 #define FIASCO_BINFILE_RELEASE   2
diff --git a/converter/other/fiasco/display.c b/converter/other/fiasco/display.c
index 368fd3c9..cf160329 100644
--- a/converter/other/fiasco/display.c
+++ b/converter/other/fiasco/display.c
@@ -307,7 +307,8 @@ alloc_ximage (x11_info_t *xinfo, unsigned width, unsigned height)
       shmem_flag = 0;
       if (fiasco_get_verbosity ())
 	 fprintf (stderr,
-		  "Shared memory not supported\nReverting to normal Xlib.\n");
+              "Shared memory does not work on this system\n"
+              "Reverting to normal Xlib.\n");
    }
 
    if (shmem_flag)
diff --git a/converter/other/fiasco/lib/image.c b/converter/other/fiasco/lib/image.c
index 56275f2e..fa3b2db5 100644
--- a/converter/other/fiasco/lib/image.c
+++ b/converter/other/fiasco/lib/image.c
@@ -449,7 +449,7 @@ write_image (const char *image_name, const image_t *image)
    
    if (image->format == FORMAT_4_2_0)
    {
-      warning ("Writing of images in 4:2:0 format not supported.");
+      warning ("We cannot write images in 4:2:0 format.");
       return;
    }
    
diff --git a/converter/other/fiasco/params.c b/converter/other/fiasco/params.c
index a4d843a8..afacbada 100644
--- a/converter/other/fiasco/params.c
+++ b/converter/other/fiasco/params.c
@@ -656,7 +656,7 @@ usage (const param_t *params, const char *progname, const char *synopsis,
     fprintf (stderr, "Usage: %s [OPTION]...%s\n", progname,
              non_opt_string ? non_opt_string : " ");
     if (synopsis != NULL)
-        fprintf (stderr, synopsis);
+        fprintf (stderr, "%s", synopsis);
     fprintf (stderr, "\n\n");
     fprintf (stderr, "Mandatory or optional arguments to long options "
              "are mandatory or optional\nfor short options too. "
diff --git a/converter/other/fiasco/pnmtofiasco.c b/converter/other/fiasco/pnmtofiasco.c
index d78ff6b1..eebd09a9 100644
--- a/converter/other/fiasco/pnmtofiasco.c
+++ b/converter/other/fiasco/pnmtofiasco.c
@@ -170,7 +170,7 @@ main (int argc, char **argv)
       return 0;
    else
    {
-      fprintf (stderr, fiasco_get_error_message ());
+       fprintf (stderr, "%s", fiasco_get_error_message ());
       fprintf (stderr, "\n");
       return 1;
    }
diff --git a/converter/other/jbig/ANNOUNCE b/converter/other/jbig/ANNOUNCE
deleted file mode 100644
index edbcc3f8..00000000
--- a/converter/other/jbig/ANNOUNCE
+++ /dev/null
@@ -1,243 +0,0 @@
-
-Version 1.2 of the JBIG-KIT lossless image compression library available
-------------------------------------------------------------------------
-
-Markus Kuhn -- 2000-04-08
-
-
-The latest release of JBIG-KIT can be downloaded over the Internet
-with anonymous ftp from
-
-  ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/JBIG/jbigkit-1.2.tar.gz
-  http://www.cl.cam.ac.uk/~mgk25/download/jbigkit-1.2.tar.gz
-
-and from a number of other servers.
-
-JBIG-KIT implements a highly effective data compression algorithm for
-bi-level high-resolution images such as fax pages or scanned
-documents.
-
-JBIG-KIT provides a portable library of compression and decompression
-functions with a documented interface that you can very easily include
-into your image or document processing software. In addition, JBIG-KIT
-provides ready-to-use compression and decompression programs with a
-simple command line interface (similar to the converters found in Jef
-Poskanzer's PBM graphics file conversion package).
-
-JBIG-KIT implements the specification
-
-  International Standard ISO/IEC 11544:1993 and ITU-T Recommendation
-  T.82(1993), "Information technology - Coded representation of picture
-  and audio information - progressive bi-level image compression",
-  <http://www.itu.ch/itudoc/itu-t/rec/t/t82_23822.html>,
-
-which is commonly referred to as the "JBIG standard". JBIG (Joint
-Bi-level Image experts Group) is the committee which developed this
-international standard for the lossless compression of images using
-arithmetic coding. Like the well-known compression algorithms JPEG and
-MPEG, also JBIG has been developed and published by the International
-Organization for Standardization (ISO) and the International
-Telecommunication Union (ITU). See also
-
-  http://www.jpeg.org/public/jbighomepage.htm
-  http://www.iso.ch/
-  http://www.itu.ch/
-
-The JBIG compression algorithm offers the following features:
-
-  - Close to state-of-the-art lossless compression ratio for high
-    resolution bi-level images.
-
-  - Around 1.1 to 1.5 times better compression ratio on typical
-    scanned documents compared to G4 fax compression (ITU-T T.6),
-    which has been the best compression algorithm for scanned
-    documents available prior to JBIG.
-
-  - Up to 30 times better compression of scanned images with dithered
-    images compared to G4 fax compression.
-
-  - Around 2 times better compression on typical 300 dpi documents
-    compared to 'gzip -9' on raw bitmaps.
-    
-  - Around 3-4 times better compression than GIF on typical 300 dpi
-    documents.
-
-  - Even much better competitive compression results on computer
-    generated images which are free of scanning distortions.
-
-  - JBIG supports hierarchical "progressive" encoding, that means it is
-    possible to encode a low resolution image first, followed by
-    resolution enhancement data. This allows for instance a document
-    browser to display already a good 75 dpi low resolution version of
-    an image, while the data necessary to reconstruct the full 300 dpi
-    version for laser printer reproduction is still arriving (say
-    over a slow network link or mass storage medium).
-
-  - The various resolution layers of a JBIG image in progressive
-    encoding mode together require not much more space than a
-    normal non-progressive mode encoded image (which JBIG also
-    supports).
-
-  - The progressive encoding mode utilizes a very sophisticated
-    resolution reduction algorithm which offers highest quality
-    low resolution versions that preserve the shape of characters as
-    well as the integrity of thin lines and dithered images.
-
-  - JBIG supports multiple bit planes and can this way also be used
-    for greyscale and color images, although the main field of
-    application is compression of bi-level images, i.e. images with
-    only two different pixel values. For greyscale images with up to
-    6 bit per pixel, JBIG performs superior to JPEG's lossless
-    mode.
-
-JBIG-KIT is free software under the GNU General Public License. For
-other license arrangements contact the author. JBIG-KIT provides a
-portable library implemented in ANSI/ISO C for encoding and decoding
-JBIG data streams together with documentation. The library is not
-intended for 8-bit or 16-bit machine architectures (e.g., old MS-DOS C
-compilers) on which a number of very efficient optimization techniques
-used in this software are not possible. For maximum performance, a
-32-bit processor is required (64-bit systems work too, of course). On
-architectures with 16-bit pointer arithmetic, only very small images
-can be processed.
-
-Special features of the JBIG-KIT implementation are:
-
-  - Fully reentrant multithread-capable design (no global or static
-    variables, isolated malloc()/free() calls, etc.).
-
-  - Capable of handling incomplete and growing JBIG data streams in
-    order to allow earliest display of low resolution versions.
-
-  - Capable of handling several incoming data streams simultaneously
-    in one single process and task.
-
-  - Especially designed with applications in mind that want to display
-    incoming data as early as possible (e.g., similar to the way in
-    which Netscape Navigator handles incoming GIF images).
-
-  - Implements all JBIG features and options including progressive and
-    sequential encoding, multiple bit planes, user specified
-    resolution reduction and deterministic prediction tables, adaptive
-    template changes for optimal performance on half-tone images,
-    deterministic prediction, typical prediction in lowest and
-    differential layers, various stripe orderings, etc. Only the SEQ
-    and HITOLO options are currently not supported by the decoder
-    (they are normally never required, but could be added later in
-    case of user requirements).
-
-  - Efficient code, optimized utilization of 32-bit processor
-    registers.
-
-  - Very easy to use documented C library interface.
-
-  - Included Gray code conversion routines for efficient encoding
-    of greyscale images.
-
-  - Ready-to-use pbmtojbg and jbgtopbm converters.
-
-
-Changes in version 1.2 (2000-04-08):
-
-  - bug in the decoder fixed, which caused the rest of the input file
-    to be skipped whenever a comment marker was encountered (special
-    thanks to Ben Rudiak-Gould <benrg@math.berkeley.edu> for
-    reporting this one)
-
-Changes in version 1.1 (1999-11-16):
-
-  - serious bug in the encoder fixed, which for a very small
-    percentage of images has caused an unterminated linked list to be
-    created internally that could have been responsible for
-    segmentation violations or non-terminating encoders
-    (special thanks to Hisashi Saiga <saiga@itl.tnr.sharp.co.jp> for
-    tracking that one down)
-
-  - minor bug in the "jbgtopbm -d" diagnostic output fixed
-
-Changes in version 1.0 (1998-04-11):
-
-  - two bugs fixed that caused the encoder and decoder to fail
-    under certain modes of operation with several bit planes
-
-  - added new functions jbg_split_planes(), jbg_dec_merge_planes(),
-    and jbg_dec_getsize_merged() for easy handling of greyscale
-    images
-
-  - added support for compressing greyscale PGM files to pbmtojbg
-    and jbgtopbm
-
-  - more changes to avoid paranoid compiler warnings
-
-Changes in version 0.9 (1996-01-09):
-
-  - encoder won't break any more on input bitmap data with incorrect
-    zero padding
-
-  - pbmtojbg displays a warning if input file has incorrect zero
-    padding
-
-  - various minor improvements suggested by Stefan Willer
-    <Stefan.Willer@unnet.wupper.DE>
-
-  - many minor changes in order to avoid warnings from paranoid
-    compilers
-
-Changes in version 0.8 (1995-09-20):
-
-  - namespace cleared up, all names externally visible from the library
-    start now with jbg_ or JBG_
-
-  - minor non-critical bug fixed which caused library to fail compatibility
-    test and showed up especially on DEC Alpha systems
-
-  - jbg_dec_gethight() is now called jbg_dec_getheight()
-
-  - filenames conform now to MS-DOS limits
-
-  - Bug in pbmtojbg fixed (handling of ASCII PBM files)
-
-Changes in version 0.7 (1995-06-10):
-
-  - more problems on 16-bit int systems and on Macintosh systems fixed
-    (special thanks to Jean-Pierre Gachen <jpg11@calvanet.calvacom.fr>)
-
-  - global Makefile
-
-Changes in version 0.6 (1995-06-08):
-
-  - memory leak fixed
-
-  - should now also work on systems where int is only 16-bit large
-
-  - changes of the JBIG "Technical Corrigendum 1" included (special
-    thanks to Dr. Sebestyen from Siemens AG for sending me a copy
-    of the draft)
-
-First release: version 0.5 (1995-05-28)
-
-
-Please send all questions, problem reports, patches, suggestions,
-success stories, comments, etc. to
-
-  mkuhn at acm.org
-
-I will try to provide free support and maintenance for this software
-at least for the next few months depending on my available time.
-
-Y2K statement: JBIG-KIT does not handle any date and time related
-data, therefore if JBIG-KIT causes you any problems related to date
-and time overflows, this would indeed be most surprising.
-
-This library has been published in the hope that it will encourage the
-development of good freely available scanned document handling and
-transmission systems for the Internet so that large amounts of scanned
-text can be made available to the global village easily.
-
-Happy compressing ...
-
-Markus Kuhn
-
---
-Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK
-email: mkuhn at acm.org,  home page: <http://www.cl.cam.ac.uk/~mgk25/>
diff --git a/converter/other/jbig/Makefile b/converter/other/jbig/Makefile
index 812bbbde..0625edd3 100644
--- a/converter/other/jbig/Makefile
+++ b/converter/other/jbig/Makefile
@@ -5,9 +5,14 @@ endif
 SUBDIR = converter/other/jbig
 VPATH=.:$(SRCDIR)/$(SUBDIR)
 
+SUBDIRS = libjbig
+
 include $(BUILDDIR)/config.mk
 
-LIBJBIG_OBJECTS = jbig.o jbig_tab.o
+# INTERNAL_JBIGLIB must be relative to the current directory, because it
+# may end up in MERGE_OBJECTS, which must be relative.
+INTERNAL_JBIGLIB = libjbig/libjbig.a
+INTERNAL_JBIGHDR_DIR = $(SRCDIR)/$(SUBDIR)/libjbig/include
 
 EXTERN_INCLUDES =
 ifneq ($(JBIGHDR_DIR),NONE)
@@ -18,32 +23,33 @@ endif
 
 ifneq ($(JBIGHDR_DIR),NONE)
   ifneq ($(JBIGLIB),NONE)
-    BINARIES = jbigtopnm pnmtojbig
+    PORTBINARIES = jbigtopnm pnmtojbig
   endif
 endif
 
+BINARIES = $(PORTBINARIES)
+
 SCRIPTS =
 
-ifeq ($(JBIGLIB),$(BUILDDIR)/$(SUBDIR)/libjbig.a)
+ifeq ($(JBIGLIB),$(INTERNAL_JBIGLIB))
   JBIGLIB_DEP = $(JBIGLIB)
 else
   # It's not our internal version; user's on his own to make sure it's built
 endif
 
-OBJECTS = $(BINARIES:%=%.o) $(LIBJBIG_OBJECTS)
-MERGE_OBJECTS = $(BINARIES:%=%.o2) $(LIBJBIG_OBJECTS)
+OBJECTS = $(BINARIES:%=%.o)
+MERGE_OBJECTS = $(BINARIES:%=%.o2)
 
 all: $(BINARIES)
 
 include $(SRCDIR)/common.mk
 
-$(BINARIES): %: %.o $(JBIGLIB_DEP) $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $< \
-	  $(shell $(LIBOPT) $(NETPBMLIB) $(JBIGLIB)) $(MATHLIB) \
-	  $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
+$(BINARIES): %: %.o $(JBIGLIB_DEP) $(LIBOPT)
+$(BINARIES): LDFLAGS_TARGET = $(shell $(LIBOPT) $(JBIGLIB))
 
-$(BUILDDIR)/$(SUBDIR)/libjbig.a: $(LIBJBIG_OBJECTS)
-	$(AR) -rc $@ $^
-	$(RANLIB) $@
+$(INTERNAL_JBIGLIB): $(BUILDDIR)/$(SUBDIR)/libjbig FORCE
+	$(MAKE) -f $(SRCDIR)/$(SUBDIR)/libjbig/Makefile \
+	  -C $(dir $@) $(notdir $@)
 
+.PHONY: FORCE
+FORCE:
diff --git a/converter/other/jbig/README.Netpbm b/converter/other/jbig/README.Netpbm
deleted file mode 100644
index 3d593b92..00000000
--- a/converter/other/jbig/README.Netpbm
+++ /dev/null
@@ -1,12 +0,0 @@
-The jbig tools are derived from the JBIG-KIT package by Marcus Kuhn,
-by Bryan Henderson on 2000.05.11.
-
-The file ANNOUNCE in this directory is from that package and gives
-details.
-
-The Netpbm tools jbigtopbm and pbmtojbig were adapted from JBIG-KIT's
-jbgtopbm and pbmtojbg.  The main difference is that the Netpbm
-versions use the Netpbm libraries.
-
-The jbig.c and jbig_table.c modules are straight from the JBIG_KIT 
-package.  They are what normally are packaged as libjbig.a.
diff --git a/converter/other/jbig/jbig.c b/converter/other/jbig/jbig.c
deleted file mode 100644
index 90295d8b..00000000
--- a/converter/other/jbig/jbig.c
+++ /dev/null
@@ -1,2905 +0,0 @@
-/*
- *  Portable Free JBIG image compression library
- *
- *  Markus Kuhn -- mkuhn@acm.org
- *
- *  $Id: jbig.c,v 1.12 2000-04-08 11:42:18+01 mgk25 Rel $
- *
- *  This module implements a portable standard C encoder and decoder
- *  using the JBIG lossless bi-level image compression algorithm as
- *  specified in International Standard ISO 11544:1993 or equivalently
- *  as specified in ITU-T Recommendation T.82. See the file jbig.doc
- *  for usage instructions and application examples.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * 
- *  If you want to use this program under different license conditions,
- *  then contact the author for an arrangement.
- *
- *  It is possible that certain products which can be built using this
- *  software module might form inventions protected by patent rights in
- *  some countries (e.g., by patents about arithmetic coding algorithms
- *  owned by IBM and AT&T in the USA). Provision of this software by the
- *  author does NOT include any licences for any patents. In those
- *  countries where a patent licence is required for certain applications
- *  of this software module, you will have to obtain such a licence
- *  yourself.
- */
-
-#ifdef DEBUG
-#include <stdio.h>
-#endif
-
-#include <stdlib.h>
-#include <assert.h>
-
-#include "jbig.h"
-
-
-/* optional export of arithmetic coder functions for test purposes */
-#ifdef TEST_CODEC
-#define ARITH
-#define ARITH_INL
-#else
-#define ARITH      static
-#ifdef __GNUC__
-#define ARITH_INL  static __inline__
-#else
-#define ARITH_INL  static
-#endif
-#endif
-
-#define MX_MAX  23     /* maximal supported mx offset for
-			* adaptive template in the encoder */
-
-#define TPB2CX  0x195  /* contexts for TP special pixels */
-#define TPB3CX  0x0e5
-#define TPDCX   0xc3f
-
-/* marker codes */
-#define MARKER_STUFF    0x00
-#define MARKER_RESERVE  0x01
-#define MARKER_SDNORM   0x02
-#define MARKER_SDRST    0x03
-#define MARKER_ABORT    0x04
-#define MARKER_NEWLEN   0x05
-#define MARKER_ATMOVE   0x06
-#define MARKER_COMMENT  0x07
-#define MARKER_ESC      0xff
-
-/* loop array indices */
-#define STRIPE  0
-#define LAYER   1
-#define PLANE   2
-
-/* special jbg_buf pointers (instead of NULL) */
-#define SDE_DONE ((struct jbg_buf *) -1)
-#define SDE_TODO ((struct jbg_buf *) 0)
-
-/* object code version id */
-
-const char jbg_version[] = 
-" JBIG-KIT " JBG_VERSION " -- Markus Kuhn -- "
-"$Id: jbig.c,v 1.12 2000-04-08 11:42:18+01 mgk25 Rel $ ";
-
-/*
- * the following array specifies for each combination of the 3
- * ordering bits, which ii[] variable represents which dimension
- * of s->sde.
- */
-static const int index[8][3] = {
-  { 2, 1, 0 },    /* no ordering bit set */
-  { -1, -1, -1},  /* SMID -> illegal combination */
-  { 2, 0, 1 },    /* ILEAVE */
-  { 1, 0, 2 },    /* SMID + ILEAVE */
-  { 0, 2, 1 },    /* SEQ */
-  { 1, 2, 0 },    /* SEQ + SMID */
-  { 0, 1, 2 },    /* SEQ + ILEAVE */
-  { -1, -1, -1 }  /* SEQ + SMID + ILEAVE -> illegal combination */
-};
-
-
-/*
- * Array [language][message] with text string error messages that correspond
- * to return values from public functions in this library.
- */
-#define NEMSG         9  /* number of error codes */
-#define NEMSG_LANG    3  /* number of supported languages */
-static const char *errmsg[NEMSG_LANG][NEMSG] = {
-  /* English (JBG_EN) */
-  {
-    "Everything is ok",                                     /* JBG_EOK */
-    "Reached specified maximum size",                       /* JBG_EOK_INTR */
-    "Unexpected end of data",                               /* JBG_EAGAIN */
-    "Not enough memory available",                          /* JBG_ENOMEM */
-    "ABORT marker found",                                   /* JBG_EABORT */
-    "Unknown marker segment encountered",                   /* JBG_EMARKER */
-    "Incremental BIE does not fit to previous one",         /* JBG_ENOCONT */
-    "Invalid data encountered",                             /* JBG_EINVAL */
-    "Unimplemented features used"                           /* JBG_EIMPL */
-  },
-  /* German (JBG_DE_8859_1) */
-  {
-    "Kein Problem aufgetreten",                             /* JBG_EOK */
-    "Angegebene maximale Bildgr\366\337e erreicht",         /* JBG_EOK_INTR */
-    "Unerwartetes Ende der Daten",                          /* JBG_EAGAIN */
-    "Nicht gen\374gend Speicher vorhanden",                 /* JBG_ENOMEM */
-    "Es wurde eine Abbruch-Sequenz gefunden",               /* JBG_EABORT */
-    "Eine unbekannte Markierungssequenz wurde gefunden",    /* JBG_EMARKER */
-    "Neue Daten passen nicht zu vorangegangenen Daten",     /* JBG_ENOCONT */
-    "Es wurden ung\374ltige Daten gefunden",                /* JBG_EINVAL */
-    "Noch nicht implementierte Optionen wurden benutzt"     /* JBG_EIMPL */
-  },
-  /* German (JBG_DE_UTF_8) */
-  {
-    "Kein Problem aufgetreten",                             /* JBG_EOK */
-    "Angegebene maximale Bildgr\303\266\303\237e erreicht", /* JBG_EOK_INTR */
-    "Unerwartetes Ende der Daten",                          /* JBG_EAGAIN */
-    "Nicht gen\303\274gend Speicher vorhanden",             /* JBG_ENOMEM */
-    "Es wurde eine Abbruch-Sequenz gefunden",               /* JBG_EABORT */
-    "Eine unbekannte Markierungssequenz wurde gefunden",    /* JBG_EMARKER */
-    "Neue Daten passen nicht zu vorangegangenen Daten",     /* JBG_ENOCONT */
-    "Es wurden ung\303\274ltige Daten gefunden",            /* JBG_EINVAL */
-    "Noch nicht implementierte Optionen wurden benutzt"     /* JBG_EIMPL */
-  }
-};
-
-
-
-/*
- * The following three functions are the only places in this code, were
- * C library memory management functions are called. The whole JBIG
- * library has been designed in order to allow multi-threaded
- * execution. no static or global variables are used, so all fuctions
- * are fully reentrant. However if you want to use this multi-thread
- * capability and your malloc, realloc and free are not reentrant,
- * then simply add the necessary semaphores or mutex primitives below.
- */
-
-static void *checked_malloc(size_t size)
-{
-  void *p;
-  
-  p = malloc(size);
-  /* Full manual exception handling is ugly here for performance
-   * reasons. If an adequate handling of lack of memory is required,
-   * then use C++ and throw a C++ exception here. */
-  if (!p)
-    abort();
-
-#if 0
-  fprintf(stderr, "%p = malloc(%ld)\n", p, (long) size);
-#endif
-
-  return p;
-}
-
-
-static void *checked_realloc(void *ptr, size_t size)
-{
-  void *p;
-
-  p = realloc(ptr, size);
-  /* Full manual exception handling is ugly here for performance
-   * reasons. If an adequate handling of lack of memory is required,
-   * then use C++ and throw a C++ exception here. */
-  if (!p)
-    abort();
-
-#if 0
-  fprintf(stderr, "%p = realloc(%p, %ld)\n", p, ptr, (long) size);
-#endif
-
-  return p;
-}
-
-
-static void checked_free(void *ptr)
-{
-  free(ptr);
-
-#if 0
-  fprintf(stderr, "free(%p)\n", ptr);
-#endif
-
-}
-
-
-
-/*
- * The next functions implement the arithmedic encoder and decoder
- * required for JBIG. The same algorithm is also used in the arithmetic
- * variant of JPEG.
- */
-
-#ifdef DEBUG
-static long encoded_pixels = 0;
-#endif
-
-ARITH void arith_encode_init(struct jbg_arenc_state *s, int reuse_st)
-{
-  int i;
-  
-  if (!reuse_st)
-    for (i = 0; i < 4096; s->st[i++] = 0);
-  s->c = 0;
-  s->a = 0x10000L;
-  s->sc = 0;
-  s->ct = 11;
-  s->buffer = -1;    /* empty */
-  
-  return;
-}
-
-
-ARITH void arith_encode_flush(struct jbg_arenc_state *s)
-{
-  unsigned long temp;
-
-#ifdef DEBUG
-  fprintf(stderr, "  encoded pixels = %ld, a = %05lx, c = %08lx\n",
-	  encoded_pixels, s->a, s->c);
-#endif
-
-  /* find the s->c in the coding interval with the largest
-   * number of trailing zero bits */
-  if ((temp = (s->a - 1 + s->c) & 0xffff0000L) < s->c)
-    s->c = temp + 0x8000;
-  else
-    s->c = temp;
-  /* send remaining bytes to output */
-  s->c <<= s->ct;
-  if (s->c & 0xf8000000L) {
-    /* one final overflow has to be handled */
-    if (s->buffer >= 0) {
-      s->byte_out(s->buffer + 1, s->file);
-      if (s->buffer + 1 == MARKER_ESC)
-	s->byte_out(MARKER_STUFF, s->file);
-    }
-    /* output 0x00 bytes only when more non-0x00 will follow */
-    if (s->c & 0x7fff800L)
-      for (; s->sc; --s->sc)
-	s->byte_out(0x00, s->file);
-  } else {
-    if (s->buffer >= 0)
-      s->byte_out(s->buffer, s->file); 
-    /* T.82 figure 30 says buffer+1 for the above line! Typo? */
-    for (; s->sc; --s->sc) {
-      s->byte_out(0xff, s->file);
-      s->byte_out(MARKER_STUFF, s->file);
-    }
-  }
-  /* output final bytes only if they are not 0x00 */
-  if (s->c & 0x7fff800L) {
-    s->byte_out((s->c >> 19) & 0xff, s->file);
-    if (((s->c >> 19) & 0xff) == MARKER_ESC)
-      s->byte_out(MARKER_STUFF, s->file);
-    if (s->c & 0x7f800L) {
-      s->byte_out((s->c >> 11) & 0xff, s->file);
-      if (((s->c >> 11) & 0xff) == MARKER_ESC)
-	s->byte_out(MARKER_STUFF, s->file);
-    }
-  }
-
-  return;
-}
-
-
-ARITH_INL void arith_encode(struct jbg_arenc_state *s, int cx, int pix) 
-{
-  extern short jbg_lsz[];
-  extern unsigned char jbg_nmps[], jbg_nlps[];
-  register unsigned lsz, ss;
-  register unsigned char *st;
-  long temp;
-
-#ifdef DEBUG
-  ++encoded_pixels;
-#endif
-
-  assert(cx >= 0 && cx < 4096);
-  st = s->st + cx;
-  ss = *st & 0x7f;
-  assert(ss < 113);
-  lsz = jbg_lsz[ss];
-
-#if 0
-  fprintf(stderr, "pix = %d, cx = %d, mps = %d, st = %3d, lsz = 0x%04x, "
-	  "a = 0x%05lx, c = 0x%08lx, ct = %2d, buf = 0x%02x\n",
-	  pix, cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct,
-	  s->buffer);
-#endif
-
-  if (((pix << 7) ^ s->st[cx]) & 0x80) {
-    /* encode the less probable symbol */
-    if ((s->a -= lsz) >= lsz) {
-      /* If the interval size (lsz) for the less probable symbol (LPS)
-       * is larger than the interval size for the MPS, then exchange
-       * the two symbols for coding efficiency, otherwise code the LPS
-       * as usual: */
-      s->c += s->a;
-      s->a = lsz;
-    }
-    /* Check whether MPS/LPS exchange is necessary
-     * and chose next probability estimator status */
-    *st &= 0x80;
-    *st ^= jbg_nlps[ss];
-  } else {
-    /* encode the more probable symbol */
-    if ((s->a -= lsz) & 0xffff8000L)
-      return;   /* A >= 0x8000 -> ready, no renormalization required */
-    if (s->a < lsz) {
-      /* If the interval size (lsz) for the less probable symbol (LPS)
-       * is larger than the interval size for the MPS, then exchange
-       * the two symbols for coding efficiency: */
-      s->c += s->a;
-      s->a = lsz;
-    }
-    /* chose next probability estimator status */
-    *st &= 0x80;
-    *st |= jbg_nmps[ss];
-  }
-
-  /* renormalization of coding interval */
-  do {
-    s->a <<= 1;
-    s->c <<= 1;
-    --s->ct;
-    if (s->ct == 0) {
-      /* another byte is ready for output */
-      temp = s->c >> 19;
-      if (temp & 0xffffff00L) {
-	/* handle overflow over all buffered 0xff bytes */
-	if (s->buffer >= 0) {
-	  ++s->buffer;
-	  s->byte_out(s->buffer, s->file);
-	  if (s->buffer == MARKER_ESC)
-	    s->byte_out(MARKER_STUFF, s->file);
-	}
-	for (; s->sc; --s->sc)
-	  s->byte_out(0x00, s->file);
-	s->buffer = temp & 0xff;  /* new output byte, might overflow later */
-	assert(s->buffer != 0xff);
-	/* can s->buffer really never become 0xff here? */
-      } else if (temp == 0xff) {
-	/* buffer 0xff byte (which might overflow later) */
-	++s->sc;
-      } else {
-	/* output all buffered 0xff bytes, they will not overflow any more */
-	if (s->buffer >= 0)
-	  s->byte_out(s->buffer, s->file);
-	for (; s->sc; --s->sc) {
-	  s->byte_out(0xff, s->file);
-	  s->byte_out(MARKER_STUFF, s->file);
-	}
-	s->buffer = temp;   /* buffer new output byte (can still overflow) */
-      }
-      s->c &= 0x7ffffL;
-      s->ct = 8;
-    }
-  } while (s->a < 0x8000);
- 
-  return;
-}
-
-
-ARITH void arith_decode_init(struct jbg_ardec_state *s, int reuse_st)
-{
-  int i;
-  
-  if (!reuse_st)
-    for (i = 0; i < 4096; s->st[i++] = 0);
-  s->c = 0;
-  s->a = 1;
-  s->ct = 0;
-  s->result = JBG_OK;
-  s->startup = 1;
-  return;
-}
-
-
-ARITH_INL int arith_decode(struct jbg_ardec_state *s, int cx)
-{
-  extern short jbg_lsz[];
-  extern unsigned char jbg_nmps[], jbg_nlps[];
-  register unsigned lsz, ss;
-  register unsigned char *st;
-  int pix;
-
-  /* renormalization */
-  while (s->a < 0x8000 || s->startup) {
-    if (s->ct < 1 && s->result != JBG_READY) {
-      /* first we have to move a new byte into s->c */
-      if (s->pscd_ptr >= s->pscd_end) {
-	s->result = JBG_MORE;
-	return -1;
-      }
-      if (*s->pscd_ptr == 0xff) 
-	if (s->pscd_ptr + 1 >= s->pscd_end) {
-	  s->result = JBG_MARKER;
-	  return -1;
-	} else {
-	  if (*(s->pscd_ptr + 1) == MARKER_STUFF) {
-	    s->c |= 0xffL << (8 - s->ct);
-	    s->ct += 8;
-	    s->pscd_ptr += 2;
-	    s->result = JBG_OK;
-	  } else
-	    s->result = JBG_READY;
-	}
-      else {
-	s->c |= (long)*(s->pscd_ptr++) << (8 - s->ct);
-	s->ct += 8;
-	s->result = JBG_OK;
-      }
-    }
-    s->c <<= 1;
-    s->a <<= 1;
-    --s->ct;
-    if (s->a == 0x10000L)
-      s->startup = 0;
-  }
-
-  st = s->st + cx;
-  ss = *st & 0x7f;
-  assert(ss < 113);
-  lsz = jbg_lsz[ss];
-
-#if 0
-  fprintf(stderr, "cx = %d, mps = %d, st = %3d, lsz = 0x%04x, a = 0x%05lx, "
-	  "c = 0x%08lx, ct = %2d\n",
-	  cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct);
-#endif
-
-  if ((s->c >> 16) < (s->a -= lsz))
-    if (s->a & 0xffff8000L)
-      return *st >> 7;
-    else {
-      /* MPS_EXCHANGE */
-      if (s->a < lsz) {
-	pix = 1 - (*st >> 7);
-	/* Check whether MPS/LPS exchange is necessary
-	 * and chose next probability estimator status */
-	*st &= 0x80;
-	*st ^= jbg_nlps[ss];
-      } else {
-	pix = *st >> 7;
-	*st &= 0x80;
-	*st |= jbg_nmps[ss];
-      }
-    }
-  else {
-    /* LPS_EXCHANGE */
-    if (s->a < lsz) {
-      s->c -= s->a << 16;
-      s->a = lsz;
-      pix = *st >> 7;
-      *st &= 0x80;
-      *st |= jbg_nmps[ss];
-    } else {
-      s->c -= s->a << 16;
-      s->a = lsz;
-      pix = 1 - (*st >> 7);
-      /* Check whether MPS/LPS exchange is necessary
-       * and chose next probability estimator status */
-      *st &= 0x80;
-      *st ^= jbg_nlps[ss];
-    }
-  }
-
-  return pix;
-}
-
-
-
-/*
- * Memory management for buffers which are used for temporarily
- * storing SDEs by the encoder.
- *
- * The following functions manage a set of struct jbg_buf storage
- * containers were each can keep JBG_BUFSIZE bytes. The jbg_buf
- * containers can be linked to form linear double-chained lists for
- * which a number of operations are provided. Blocks which are
- * tempoarily not used any more are returned to a freelist which each
- * encoder keeps. Only the destructor of the encoder actually returns
- * the block via checked_free() to the stdlib memory management.
- */
-
-
-/*
- * Allocate a new buffer block and initialize it. Try to get it from
- * the free_list, and if it is empty, call checked_malloc().
- */
-static struct jbg_buf *jbg_buf_init(struct jbg_buf **free_list)
-{
-  struct jbg_buf *new_block;
-  
-  /* Test whether a block from the free list is available */
-  if (*free_list) {
-    new_block = *free_list;
-    *free_list = new_block->next;
-  } else {
-    /* request a new memory block */
-    new_block = (struct jbg_buf *) checked_malloc(sizeof(struct jbg_buf));
-  }
-  new_block->len = 0;
-  new_block->next = NULL;
-  new_block->previous = NULL;
-  new_block->last = new_block;
-  new_block->free_list = free_list;
-
-  return new_block;
-}
-
-
-/*
- * Return an entire free_list to the memory management of stdlib.
- * This is only done by jbg_enc_free().
- */
-static void jbg_buf_free(struct jbg_buf **free_list)
-{
-  struct jbg_buf *tmp;
-  
-  while (*free_list) {
-    tmp = (*free_list)->next;
-    checked_free(*free_list);
-    *free_list = tmp;
-  }
-  
-  return;
-}
-
-
-/*
- * Append a single byte to a single list that starts with the block
- * *(struct jbg_buf *) head. The type of *head is void here in order to
- * keep the interface of the arithmetic encoder gereric, which uses this
- * function as a call-back function in order to deliver single bytes
- * for a PSCD.
- */
-static void jbg_buf_write(int b, void *head)
-{
-  struct jbg_buf *now;
-
-  now = ((struct jbg_buf *) head)->last;
-  if (now->len < JBG_BUFSIZE - 1) {
-    now->d[now->len++] = b;
-    return;
-  }
-  now->next = jbg_buf_init(((struct jbg_buf *) head)->free_list);
-  now->next->previous = now;
-  now->next->d[now->next->len++] = b;
-  ((struct jbg_buf *) head)->last = now->next;
-
-  return;
-}
-
-
-/*
- * Remove any trailing zero bytes from the end of a linked jbg_buf list,
- * however make sure that no zero byte is removed which directly
- * follows a 0xff byte (i.e., keep MARKER_ESC MARKER_STUFF sequences
- * intact). This function is used to remove any redundant final zero
- * bytes from a PSCD.
- */
-static void jbg_buf_remove_zeros(struct jbg_buf *head)
-{
-  struct jbg_buf *last;
-
-  while (1) {
-    /* remove trailing 0x00 in last block of list until this block is empty */
-    last = head->last;
-    while (last->len && last->d[last->len - 1] == 0)
-      last->len--;
-    /* if block became really empty, remove it in case it is not the
-     * only remaining block and then loop to next block */
-    if (last->previous && !last->len) {
-      head->last->next = *head->free_list;
-      *head->free_list = head->last;
-      head->last = last->previous;
-      head->last->next = NULL;
-    } else
-      break;
-  }
-
-  /*
-   * If the final non-zero byte is 0xff (MARKER_ESC), then we just have
-   * removed a MARKER_STUFF and we will append it again now in order
-   * to preserve PSCD status of byte stream.
-   */
-  if (head->last->len && head->last->d[head->last->len - 1] == MARKER_ESC)
-    jbg_buf_write(MARKER_STUFF, head);
- 
-  return;
-}
-
-
-/*
- * The jbg_buf list which starts with block *new_prefix is concatenated
- * with the list which starts with block **start and *start will then point
- * to the first block of the new list.
- */
-static void jbg_buf_prefix(struct jbg_buf *new_prefix, struct jbg_buf **start)
-{
-  new_prefix->last->next = *start;
-  new_prefix->last->next->previous = new_prefix->last;
-  new_prefix->last = new_prefix->last->next->last;
-  *start = new_prefix;
-  
-  return;
-}
-
-
-/*
- * Send the contents of a jbg_buf list that starts with block **head to
- * the call back function data_out and return the blocks of the jbg_buf
- * list to the freelist from which these jbg_buf blocks have been taken.
- * After the call, *head == NULL.
- */
-static void jbg_buf_output(struct jbg_buf **head,
-			void (*data_out)(unsigned char *start,
-					 size_t len, void *file),
-			void *file)
-{
-  struct jbg_buf *tmp;
-  
-  while (*head) {
-    data_out((*head)->d, (*head)->len, file);
-    tmp = (*head)->next;
-    (*head)->next = *(*head)->free_list;
-    *(*head)->free_list = *head;
-    *head = tmp;
-  }
-  
-  return;
-}
-
-
-/*
- * Calculate y = ceil(x/2) applied n times. This function is used to
- * determine the number of pixels per row or column after n resolution
- * reductions. E.g. X[d-1] = jbg_ceil_half(X[d], 1) and X[0] =
- * jbg_ceil_half(X[d], d) as defined in clause 6.2.3 of T.82.
- */
-unsigned long jbg_ceil_half(unsigned long x, int n)
-{
-  unsigned long mask;
-  
-  mask = (1UL << n) - 1;     /* the lowest n bits are 1 here */
-  return (x >> n) + ((mask & x) != 0);
-}
-
-
-/*
- * Initialize the status struct for the encoder.
- */
-void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y,
-                  int planes, unsigned char **p,
-                  void (*data_out)(unsigned char *start, size_t len,
-				   void *file),
-		  void *file)
-{
-  unsigned long l, lx;
-  int i;
-  size_t bufsize;
-
-  extern char jbg_resred[], jbg_dptable[];
-
-  s->xd = x;
-  s->yd = y;
-  s->planes = planes;
-  s->data_out = data_out;
-  s->file = file;
-
-  s->d = 0;
-  s->dl = 0;
-  s->dh = s->d;
-  s->l0 = jbg_ceil_half(s->yd, s->d) / 35;   /* 35 stripes/image */
-  while ((s->l0 << s->d) > 128)              /* but <= 128 lines/stripe */
-    --s->l0;
-  if (s->l0 < 2) s->l0 = 2;
-  s->mx = 8;
-  s->my = 0;
-  s->order = JBG_ILEAVE | JBG_SMID;
-  s->options = JBG_TPBON | JBG_TPDON | JBG_DPON;
-  s->dppriv = jbg_dptable;
-  s->res_tab = jbg_resred;
-  
-  s->highres = checked_malloc(planes * sizeof(int));
-  s->lhp[0] = p;
-  s->lhp[1] = checked_malloc(planes * sizeof(unsigned char *));
-  bufsize = ((jbg_ceil_half(x, 1) + 7) / 8) * jbg_ceil_half(y, 1);
-  for (i = 0; i < planes; i++) {
-    s->highres[i] = 0;
-    s->lhp[1][i] = checked_malloc(sizeof(unsigned char) * bufsize);
-  }
-  
-  s->free_list = NULL;
-  s->s = (struct jbg_arenc_state *) 
-    checked_malloc(s->planes * sizeof(struct jbg_arenc_state));
-  s->tx = (int *) checked_malloc(s->planes * sizeof(int));
-  lx = jbg_ceil_half(x, 1);
-  s->tp = (char *) checked_malloc(lx * sizeof(char));
-  for (l = 0; l < lx; s->tp[l++] = 2);
-  s->sde = NULL;
-
-  return;
-}
-
-
-/*
- * This function selects the number of differential layers based on
- * the maximum size requested for the lowest resolution layer. If
- * possible, a number of differential layers is selected, which will
- * keep the size of the lowest resolution layer below or equal to the
- * given width x and height y. However not more than 6 differential
- * resolution layers will be used. In addition, a reasonable value for
- * l0 (height of one stripe in the lowest resolution layer) is
- * selected, which obeys the recommended limitations for l0 in annex A
- * and C of the JBIG standard. The selected number of resolution layers
- * is returned. 
- */
-int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, 
-		   unsigned long y)
-{
-  for (s->d = 0; s->d < 6; s->d++)
-    if (jbg_ceil_half(s->xd, s->d) <= x && jbg_ceil_half(s->yd, s->d) <= y)
-      break;
-  s->dl = 0;
-  s->dh = s->d;
-
-  s->l0 = jbg_ceil_half(s->yd, s->d) / 35;  /* 35 stripes/image */
-  while ((s->l0 << s->d) > 128)             /* but <= 128 lines/stripe */
-    --s->l0;
-  if (s->l0 < 2) s->l0 = 2;
-
-  return s->d;
-}
-
-
-/*
- * As an alternative to jbg_enc_lrlmax(), the following function allows
- * to specify the number of layers directly. The stripe height and layer
- * range is also adjusted automatically here.
- */
-void jbg_enc_layers(struct jbg_enc_state *s, int d)
-{
-  if (d < 0 || d > 255)
-    return;
-  s->d  = d;
-  s->dl = 0;
-  s->dh = s->d;
-
-  s->l0 = jbg_ceil_half(s->yd, s->d) / 35;  /* 35 stripes/image */
-  while ((s->l0 << s->d) > 128)             /* but <= 128 lines/stripe */
-    --s->l0;
-  if (s->l0 < 2) s->l0 = 2;
-
-  return;
-}
-
-
-/*
- * Specify the highest and lowest resolution layers which will be
- * written to the output file. Call this function not before
- * jbg_enc_layers() or jbg_enc_lrlmax(), because these two functions
- * reset the lowest and highest resolution layer to default values.
- * Negative values are ignored. The total number of layers is returned.
- */
-int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh)
-{
-  if (dl >= 0     && dl <= s->d) s->dl = dl;
-  if (dh >= s->dl && dh <= s->d) s->dh = dh;
-
-  return s->d;
-}
-
-
-/*
- * The following function allows to specify the bits describing the
- * options of the format as well as the maximum AT movement window and
- * the number of layer 0 lines per stripes.
- */
-void jbg_enc_options(struct jbg_enc_state *s, int order, int options,
-		     long l0, int mx, int my)
-{
-  if (order >= 0 && order <= 0x0f) s->order = order;
-  if (options >= 0) s->options = options;
-  if (l0 >= 0) s->l0 = l0;
-  if (mx >= 0 && my < 128) s->mx = mx;
-  if (my >= 0 && my < 256) s->my = my;
-
-  return;
-}
-
-
-/*
- * This function actually does all the tricky work involved in producing
- * a SDE, which is stored in the appropriate s->sde[][][] element
- * for later output in the correct order.
- */
-static void encode_sde(struct jbg_enc_state *s,
-		       long stripe, int layer, int plane)
-{
-  unsigned char *hp, *lp1, *lp2, *p0, *p1, *q1, *q2;
-  unsigned long hl, ll, hx, hy, lx, ly, hbpl, lbpl;
-  unsigned long line_h0 = 0, line_h1 = 0;
-  unsigned long line_h2, line_h3, line_l1, line_l2, line_l3;
-  struct jbg_arenc_state *se;
-  unsigned long i, j, y;
-  unsigned t;
-  int ltp, ltp_old, cx;
-  unsigned long c_all, c[MX_MAX + 1], cmin, cmax, clmin, clmax;
-  int tmax, at_determined;
-  int new_tx;
-  long new_tx_line = -1;
-  struct jbg_buf *new_jbg_buf;
-
-#ifdef DEBUG
-  static long tp_lines, tp_exceptions, tp_pixels, dp_pixels;
-  static long encoded_pixels;
-#endif
-
-  /* return immediately if this stripe has already been encoded */
-  if (s->sde[stripe][layer][plane] != SDE_TODO)
-    return;
-
-#ifdef DEBUG
-  if (stripe == 0)
-    tp_lines = tp_exceptions = tp_pixels = dp_pixels = encoded_pixels = 0;
-  fprintf(stderr, "encode_sde: s/d/p = %2ld/%2d/%2d\n",
-	  stripe, layer, plane);
-#endif
-
-  /* number of lines per stripe in highres image */
-  hl = s->l0 << layer;
-  /* number of lines per stripe in lowres image */
-  ll = hl >> 1;
-  /* current line number in highres image */
-  y = stripe * hl;
-  /* number of pixels in highres image */
-  hx = jbg_ceil_half(s->xd, s->d - layer);
-  hy = jbg_ceil_half(s->yd, s->d - layer);
-  /* number of pixels in lowres image */
-  lx = jbg_ceil_half(hx, 1);
-  ly = jbg_ceil_half(hy, 1);
-  /* bytes per line in highres and lowres image */
-  hbpl = (hx + 7) / 8;
-  lbpl = (lx + 7) / 8;
-  /* pointer to first image byte of highres stripe */
-  hp = s->lhp[s->highres[plane]][plane] + stripe * hl * hbpl;
-  lp2 = s->lhp[1 - s->highres[plane]][plane] + stripe * ll * lbpl;
-  lp1 = lp2 + lbpl;
-  
-  /* initialize arithmetic encoder */
-  se = s->s + plane;
-  arith_encode_init(se, stripe != 0);
-  s->sde[stripe][layer][plane] = jbg_buf_init(&s->free_list);
-  se->byte_out = jbg_buf_write;
-  se->file = s->sde[stripe][layer][plane];
-
-  /* initialize adaptive template movement algorithm */
-  c_all = 0;
-  for (t = 0; t <= s->mx; t++)
-    c[t] = 0;
-  if (stripe == 0)
-    s->tx[plane] = 0;
-  new_tx = -1;
-  at_determined = 0;  /* we haven't yet decided the template move */
-  if (s->mx == 0)
-    at_determined = 1;
-
-  /* initialize typical prediction */
-  ltp = 0;
-  if (stripe == 0)
-    ltp_old = 0;
-  else {
-    ltp_old = 1;
-    p1 = hp - hbpl;
-    if (y > 1) {
-      q1 = p1 - hbpl;
-      while (p1 < hp && (ltp_old = (*p1++ == *q1++)) != 0);
-    } else
-      while (p1 < hp && (ltp_old = (*p1++ == 0)) != 0);
-  }
-
-  if (layer == 0) {
-
-    /*
-     *  Encode lowest resolution layer
-     */
-
-    for (i = 0; i < hl && y < hy; i++, y++) {
-
-      /* check whether it is worth to perform an ATMOVE */
-      if (!at_determined && c_all > 2048) {
-	cmin = clmin = 0xffffffffL;
-	cmax = clmax = 0;
-	tmax = 0;
-	for (t = (s->options & JBG_LRLTWO) ? 5 : 3; t <= s->mx; t++) {
-	  if (c[t] > cmax) cmax = c[t];
-	  if (c[t] < cmin) cmin = c[t];
-	  if (c[t] > c[tmax]) tmax = t;
-	}
-	clmin = (c[0] < cmin) ? c[0] : cmin;
-	clmax = (c[0] > cmax) ? c[0] : cmax;
-	if (c_all - cmax < (c_all >> 3) &&
-	    cmax - c[s->tx[plane]] > c_all - cmax &&
-	    cmax - c[s->tx[plane]] > (c_all >> 4) &&
-	    /*                     ^ T.82 says here < !!! Typo ? */
-	    cmax - (c_all - c[s->tx[plane]]) > c_all - cmax &&
-	    cmax - (c_all - c[s->tx[plane]]) > (c_all >> 4) &&
-	    cmax - cmin > (c_all >> 2) &&
-	    (s->tx[plane] || clmax - clmin > (c_all >> 3))) {
-	  /* we have decided to perform an ATMOVE */
-	  new_tx = tmax;
-	  if (!(s->options & JBG_DELAY_AT)) {
-	    new_tx_line = i;
-	    s->tx[plane] = new_tx;
-	  }
-	}
-	at_determined = 1;
-      }
-      
-      /* typical prediction */
-      if (s->options & JBG_TPBON) {
-	ltp = 1;
-	p1 = hp;
-	if (y > 0) {
-	  q1 = hp - hbpl;
-	  while (q1 < hp && (ltp = (*p1++ == *q1++)) != 0);
-	} else
-	  while (p1 < hp + hbpl && (ltp = (*p1++ == 0)) != 0);
-	arith_encode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX,
-		     ltp == ltp_old);
-#ifdef DEBUG
-	tp_lines += ltp;
-#endif
-	ltp_old = ltp;
-	if (ltp) {
-	  /* skip next line */
-	  hp += hbpl;
-	  continue;
-	}
-      }
-
-      /*
-       * Layout of the variables line_h1, line_h2, line_h3, which contain
-       * as bits the neighbour pixels of the currently coded pixel X:
-       *
-       *          76543210765432107654321076543210     line_h3
-       *          76543210765432107654321076543210     line_h2
-       *  76543210765432107654321X76543210             line_h1
-       */
-      
-      line_h1 = line_h2 = line_h3 = 0;
-      if (y > 0) line_h2 = (long)*(hp - hbpl) << 8;
-      if (y > 1) line_h3 = (long)*(hp - hbpl - hbpl) << 8;
-      
-      /* encode line */
-      for (j = 0; j < hx; hp++) {
-	line_h1 |= *hp;
-	if (j < hbpl * 8 - 8 && y > 0) {
-	  line_h2 |= *(hp - hbpl + 1);
-	  if (y > 1)
-	    line_h3 |= *(hp - hbpl - hbpl + 1);
-	}
-	if (s->options & JBG_LRLTWO) {
-	  /* two line template */
-	  do {
-	    line_h1 <<= 1;  line_h2 <<= 1;  line_h3 <<= 1;
-	    if (s->tx[plane])
-	      arith_encode(se, (((line_h2 >> 10) & 0x3e0) |
-				((line_h1 >> (4 + s->tx[plane])) & 0x010) |
-				((line_h1 >>  9) & 0x00f)),
-			   (line_h1 >> 8) & 1);
-	    else
-	      arith_encode(se, (((line_h2 >> 10) & 0x3f0) |
-				((line_h1 >>  9) & 0x00f)),
-			   (line_h1 >> 8) & 1);
-#ifdef DEBUG
-	    encoded_pixels++;
-#endif
-	    /* statistics for adaptive template changes */
-	    if (!at_determined && j >= s->mx && j < hx-2) {
-	      c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100);
-	      for (t = 5; t <= s->mx; t++)
-		c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100);
-	      ++c_all;
-	    }
-	  } while (++j & 7 && j < hx);
-	} else {
-	  /* three line template */
-	  do {
-	    line_h1 <<= 1;  line_h2 <<= 1;  line_h3 <<= 1;
-	    if (s->tx[plane]) 
-	      arith_encode(se, (((line_h3 >>  8) & 0x380) |
-				((line_h2 >> 12) & 0x078) |
-				((line_h1 >> (6 + s->tx[plane])) & 0x004) |
-				((line_h1 >>  9) & 0x003)),
-			   (line_h1 >> 8) & 1);
-	    else
-	      arith_encode(se, (((line_h3 >>  8) & 0x380) |
-				((line_h2 >> 12) & 0x07c) |
-				((line_h1 >>  9) & 0x003)),
-			   (line_h1 >> 8) & 1);
-#ifdef DEBUG
-	    encoded_pixels++;
-#endif
-	    /* statistics for adaptive template changes */
-	    if (!at_determined && j >= s->mx && j < hx-2) {
-	      c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100);
-	      for (t = 3; t <= s->mx; t++)
-		c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100);
-	      ++c_all;
-	    }
-	  } while (++j & 7 && j < hx);
-	} /* if (s->options & JBG_LRLTWO) */
-      } /* for (j = ...) */
-    } /* for (i = ...) */
-
-  } else {
-
-    /*
-     *  Encode differential layer
-     */
-    
-    for (i = 0; i < hl && y < hy; i++, y++) {
-
-      /* check whether it is worth to perform an ATMOVE */
-      if (!at_determined && c_all > 2048) {
-	cmin = clmin = 0xffffffffL;
-	cmax = clmax = 0;
-	tmax = 0;
-	for (t = 3; t <= s->mx; t++) {
-	  if (c[t] > cmax) cmax = c[t];
-	  if (c[t] < cmin) cmin = c[t];
-	  if (c[t] > c[tmax]) tmax = t;
-	}
-	clmin = (c[0] < cmin) ? c[0] : cmin;
-	clmax = (c[0] > cmax) ? c[0] : cmax;
-	if (c_all - cmax < (c_all >> 3) &&
-	    cmax - c[s->tx[plane]] > c_all - cmax &&
-	    cmax - c[s->tx[plane]] > (c_all >> 4) &&
-	    /*                     ^ T.82 says here < !!! Typo ? */
-	    cmax - (c_all - c[s->tx[plane]]) > c_all - cmax &&
-	    cmax - (c_all - c[s->tx[plane]]) > (c_all >> 4) &&
-	    cmax - cmin > (c_all >> 2) &&
-	    (s->tx[plane] || clmax - clmin > (c_all >> 3))) {
-	  /* we have decided to perform an ATMOVE */
-	  new_tx = tmax;
-	  if (!(s->options & JBG_DELAY_AT)) {
-	    new_tx_line = i;
-	    s->tx[plane] = new_tx;
-	  }
-#ifdef DEBUG
-	  fprintf(stderr, "ATMOVE: line=%ld, tx=%d, c_all=%ld\n",
-		  i, new_tx, c_all);
-#endif
-	}
-	at_determined = 1;
-      }
-      
-      if ((i >> 1) >= ll - 1 || (y >> 1) >= ly - 1)
-	lp1 = lp2;
-
-      /* typical prediction */
-      if (s->options & JBG_TPDON && (i & 1) == 0) {
-	q1 = lp1; q2 = lp2;
-	p0 = p1 = hp;
-	if (i < hl - 1 && y < hy - 1)
-	  p0 = hp + hbpl;
-	if (y > 1)
-	  line_l3 = (long)*(q2 - lbpl) << 8;
-	else
-	  line_l3 = 0;
-	line_l2 = (long)*q2 << 8;
-	line_l1 = (long)*q1 << 8;
-	ltp = 1;
-	for (j = 0; j < lx && ltp; q1++, q2++) {
-	  if (j < lbpl * 8 - 8) {
-	    if (y > 1)
-	      line_l3 |= *(q2 - lbpl + 1);
-	    line_l2 |= *(q2 + 1);
-	    line_l1 |= *(q1 + 1);
-	  }
-	  do {
-	    if ((j >> 2) < hbpl) {
-	      line_h1 = *(p1++);
-	      line_h0 = *(p0++);
-	    }
-	    do {
-	      line_l3 <<= 1;
-	      line_l2 <<= 1;
-	      line_l1 <<= 1;
-	      line_h1 <<= 2;
-	      line_h0 <<= 2;
-	      cx = (((line_l3 >> 15) & 0x007) |
-		    ((line_l2 >> 12) & 0x038) |
-		    ((line_l1 >> 9)  & 0x1c0));
-	      if (cx == 0x000)
-		if ((line_h1 & 0x300) == 0 && (line_h0 & 0x300) == 0)
-		  s->tp[j] = 0;
-		else {
-		  ltp = 0;
-#ifdef DEBUG
-		  tp_exceptions++;
-#endif
-		}
-	      else if (cx == 0x1ff)
-		if ((line_h1 & 0x300) == 0x300 && (line_h0 & 0x300) == 0x300)
-		  s->tp[j] = 1;
-		else {
-		  ltp = 0;
-#ifdef DEBUG
-		  tp_exceptions++;
-#endif
-		}
-	      else
-		s->tp[j] = 2;
-	    } while (++j & 3 && j < lx);
-	  } while (j & 7 && j < lx);
-	} /* for (j = ...) */
-	arith_encode(se, TPDCX, !ltp);
-#ifdef DEBUG
-	tp_lines += ltp;
-#endif
-      }
-
-
-      /*
-       * Layout of the variables line_h1, line_h2, line_h3, which contain
-       * as bits the high resolution neighbour pixels of the currently coded
-       * highres pixel X:
-       *
-       *            76543210 76543210 76543210 76543210     line_h3
-       *            76543210 76543210 76543210 76543210     line_h2
-       *   76543210 76543210 7654321X 76543210              line_h1
-       *
-       * Layout of the variables line_l1, line_l2, line_l3, which contain
-       * the low resolution pixels near the currently coded pixel as bits.
-       * The lowres pixel in which the currently coded highres pixel is
-       * located is marked as Y:
-       *
-       *            76543210 76543210 76543210 76543210     line_l3
-       *            76543210 7654321Y 76543210 76543210     line_l2
-       *            76543210 76543210 76543210 76543210     line_l1
-       */
-      
-
-      line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0;
-      if (y > 0) line_h2 = (long)*(hp - hbpl) << 8;
-      if (y > 1) {
-	line_h3 = (long)*(hp - hbpl - hbpl) << 8;
-	line_l3 = (long)*(lp2 - lbpl) << 8;
-      }
-      line_l2 = (long)*lp2 << 8;
-      line_l1 = (long)*lp1 << 8;
-      
-      /* encode line */
-      for (j = 0; j < hx; lp1++, lp2++) {
-	if ((j >> 1) < lbpl * 8 - 8) {
-	  if (y > 1)
-	    line_l3 |= *(lp2 - lbpl + 1);
-	  line_l2 |= *(lp2 + 1);
-	  line_l1 |= *(lp1 + 1);
-	}
-	do {
-
-	  assert(hp - (s->lhp[s->highres[plane]][plane] +
-		       (stripe * hl + i) * hbpl)
-		 == (ptrdiff_t) j >> 3);
-
-	  assert(lp2 - (s->lhp[1-s->highres[plane]][plane] +
-			(stripe * ll + (i>>1)) * lbpl)
-		 == (ptrdiff_t) j >> 4);
-
-	  line_h1 |= *(hp++);
-	  if (j < hbpl * 8 - 8) {
-	    if (y > 0) {
-	      line_h2 |= *(hp - hbpl);
-	      if (y > 1)
-		line_h3 |= *(hp - hbpl - hbpl);
-	    }
-	  }
-	  do {
-	    line_l1 <<= 1;  line_l2 <<= 1;  line_l3 <<= 1;
-	    if (ltp && s->tp[j >> 1] < 2) {
-	      /* pixel are typical and have not to be encoded */
-	      line_h1 <<= 2;  line_h2 <<= 2;  line_h3 <<= 2;
-#ifdef DEBUG
-	      do {
-		++tp_pixels;
-	      } while (++j & 1 && j < hx);
-#else
-	      j += 2;
-#endif
-	    } else
-	      do {
-		line_h1 <<= 1;  line_h2 <<= 1;  line_h3 <<= 1;
-
-		/* deterministic prediction */
-		if (s->options & JBG_DPON) {
-		  if ((y & 1) == 0) {
-		    if ((j & 1) == 0) {
-		      /* phase 0 */
-		      if (s->dppriv[((line_l3 >> 16) & 0x003) |
-				    ((line_l2 >> 14) & 0x00c) |
-				    ((line_h1 >> 5)  & 0x010) |
-				    ((line_h2 >> 10) & 0x0e0)] < 2) {
-#ifdef DEBUG
-			++dp_pixels;
-#endif
-			continue;
-		      }
-		    } else {
-		      /* phase 1 */
-		      if (s->dppriv[(((line_l3 >> 16) & 0x003) |
-				     ((line_l2 >> 14) & 0x00c) |
-				     ((line_h1 >> 5)  & 0x030) |
-				     ((line_h2 >> 10) & 0x1c0)) + 256] < 2) {
-#ifdef DEBUG
-			++dp_pixels;
-#endif
-			continue;
-		      }
-		    }
-		  } else {
-		    if ((j & 1) == 0) {
-		      /* phase 2 */
-		      if (s->dppriv[(((line_l3 >> 16) & 0x003) |
-				     ((line_l2 >> 14) & 0x00c) |
-				     ((line_h1 >> 5)  & 0x010) |
-				     ((line_h2 >> 10) & 0x0e0) |
-				     ((line_h3 >> 7) & 0x700)) + 768] < 2) {
-#ifdef DEBUG
-			++dp_pixels;
-#endif
-			continue;
-		      }
-		    } else {
-		      /* phase 3 */
-		      if (s->dppriv[(((line_l3 >> 16) & 0x003) |
-				     ((line_l2 >> 14) & 0x00c) |
-				     ((line_h1 >> 5)  & 0x030) |
-				     ((line_h2 >> 10) & 0x1c0) |
-				     ((line_h3 >> 7)  & 0xe00)) + 2816] < 2) {
-#ifdef DEBUG
-			++dp_pixels;
-#endif
-			continue;
-		      }
-		    }	
-		  }	
-		}
-
-		/* determine context */
-		if (s->tx[plane])
-		  cx = (((line_h1 >> 9)  & 0x003) |
-			((line_h1 >> (4 + s->tx[plane])) & 0x010) |
-			((line_h2 >> 13) & 0x00c) |
-			((line_h3 >> 11) & 0x020));
-		else
-		  cx = (((line_h1 >> 9)  & 0x003) |
-			((line_h2 >> 13) & 0x01c) |
-			((line_h3 >> 11) & 0x020));
-		if (j & 1)
-		  cx |= (((line_l2 >> 9)  & 0x0c0) |
-			 ((line_l1 >> 7)  & 0x300)) | (1UL << 10);
-		else
-		  cx |= (((line_l2 >> 10) & 0x0c0) |
-			 ((line_l1 >> 8)  & 0x300));
-		cx |= (y & 1) << 11;
-
-		arith_encode(se, cx, (line_h1 >> 8) & 1);
-#ifdef DEBUG
-		encoded_pixels++;
-#endif
-		
-		/* statistics for adaptive template changes */
-		if (!at_determined && j >= s->mx) {
-		  c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100);
-		  for (t = 3; t <= s->mx; t++)
-		    c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100);
-		  ++c_all;
-		}
-		
-	      } while (++j & 1 && j < hx);
-	  } while (j & 7 && j < hx);
-	} while (j & 15 && j < hx);
-      } /* for (j = ...) */
-
-      /* low resolution pixels are used twice */
-      if ((i & 1) == 0) {
-	lp1 -= lbpl;
-	lp2 -= lbpl;
-      }
-      
-    } /* for (i = ...) */
-  }
-  
-  arith_encode_flush(se);
-  jbg_buf_remove_zeros(s->sde[stripe][layer][plane]);
-  jbg_buf_write(MARKER_ESC, s->sde[stripe][layer][plane]);
-  jbg_buf_write(MARKER_SDNORM, s->sde[stripe][layer][plane]);
-
-  /* add ATMOVE */
-  if (new_tx != -1) {
-    if (s->options & JBG_DELAY_AT) {
-      /* ATMOVE will become active at the first line of the next stripe */
-      s->tx[plane] = new_tx;
-      jbg_buf_write(MARKER_ESC, s->sde[stripe][layer][plane]);
-      jbg_buf_write(MARKER_ATMOVE, s->sde[stripe][layer][plane]);
-      jbg_buf_write(0, s->sde[stripe][layer][plane]);
-      jbg_buf_write(0, s->sde[stripe][layer][plane]);
-      jbg_buf_write(0, s->sde[stripe][layer][plane]);
-      jbg_buf_write(0, s->sde[stripe][layer][plane]);
-      jbg_buf_write(s->tx[plane], s->sde[stripe][layer][plane]);
-      jbg_buf_write(0, s->sde[stripe][layer][plane]);
-    } else {
-      /* ATMOVE has already become active during this stripe
-       * => we have to prefix the SDE data with an ATMOVE marker */
-      new_jbg_buf = jbg_buf_init(&s->free_list);
-      jbg_buf_write(MARKER_ESC, new_jbg_buf);
-      jbg_buf_write(MARKER_ATMOVE, new_jbg_buf);
-      jbg_buf_write((new_tx_line >> 24) & 0xff, new_jbg_buf);
-      jbg_buf_write((new_tx_line >> 16) & 0xff, new_jbg_buf);
-      jbg_buf_write((new_tx_line >> 8) & 0xff, new_jbg_buf);
-      jbg_buf_write(new_tx_line & 0xff, new_jbg_buf);
-      jbg_buf_write(new_tx, new_jbg_buf);
-      jbg_buf_write(0, new_jbg_buf);
-      jbg_buf_prefix(new_jbg_buf, &s->sde[stripe][layer][plane]);
-    }
-  }
-
-#if 0
-  if (stripe == s->stripes - 1)
-    fprintf(stderr, "tp_lines = %ld, tp_exceptions = %ld, tp_pixels = %ld, "
-	    "dp_pixels = %ld, encoded_pixels = %ld\n",
-	    tp_lines, tp_exceptions, tp_pixels, dp_pixels, encoded_pixels);
-#endif
-
-  return;
-}
-
-
-/*
- * Create the next lower resolution version of an image
- */
-static void resolution_reduction(struct jbg_enc_state *s, int plane,
-				 int higher_layer)
-{
-  unsigned long hx, hy, lx, ly, hbpl, lbpl;
-  unsigned char *hp1, *hp2, *hp3, *lp;
-  unsigned long line_h1, line_h2, line_h3, line_l2;
-  unsigned long i, j;
-  int pix, k, l;
-
-  /* number of pixels in highres image */
-  hx = jbg_ceil_half(s->xd, s->d - higher_layer);
-  hy = jbg_ceil_half(s->yd, s->d - higher_layer);
-  /* number of pixels in lowres image */
-  lx = jbg_ceil_half(hx, 1);
-  ly = jbg_ceil_half(hy, 1);
-  /* bytes per line in highres and lowres image */
-  hbpl = (hx + 7) / 8;
-  lbpl = (lx + 7) / 8;
-  /* pointers to first image bytes */
-  hp2 = s->lhp[s->highres[plane]][plane];
-  hp1 = hp2 + hbpl;
-  hp3 = hp2 - hbpl;
-  lp = s->lhp[1 - s->highres[plane]][plane];
-  
-#ifdef DEBUG
-  fprintf(stderr, "resolution_reduction: plane = %d, higher_layer = %d\n",
-	  plane, higher_layer);
-#endif
-
-  /*
-   * Layout of the variables line_h1, line_h2, line_h3, which contain
-   * as bits the high resolution neighbour pixels of the currently coded
-   * lowres pixel /\:
-   *              \/
-   *
-   *   76543210 76543210 76543210 76543210     line_h3
-   *   76543210 76543210 765432/\ 76543210     line_h2
-   *   76543210 76543210 765432\/ 76543210     line_h1
-   *
-   * Layout of the variable line_l2, which contains the low resolution
-   * pixels near the currently coded pixel as bits. The lowres pixel
-   * which is currently coded is marked as X:
-   *
-   *   76543210 76543210 76543210 76543210     line_l2
-   *                            X
-   */
-      
-  for (i = 0; i < ly; i++) {
-    if (2*i + 1 >= hy)
-      hp1 = hp2;
-    pix = 0;
-    line_h1 = line_h2 = line_h3 = line_l2 = 0;
-    for (j = 0; j < lbpl * 8; j += 8) {
-      *lp = 0;
-      line_l2 |= i ? lp[-lbpl] : 0;
-      for (k = 0; k < 8 && j + k < lx; k += 4) {
-	if (((j + k) >> 2) < hbpl) {
-	  line_h3 |= i ? *hp3 : 0;
-	  ++hp3;
-	  line_h2 |= *(hp2++);
-	  line_h1 |= *(hp1++);
-	}
-	for (l = 0; l < 4 && j + k + l < lx; l++) {
-	  line_h3 <<= 2;
-	  line_h2 <<= 2;
-	  line_h1 <<= 2;
-	  line_l2 <<= 1;
-	  pix = s->res_tab[((line_h1 >> 8) & 0x007) |
-			   ((line_h2 >> 5) & 0x038) |
-			   ((line_h3 >> 2) & 0x1c0) |
-			   (pix << 9) | ((line_l2 << 2) & 0xc00)];
-	  *lp = (*lp << 1) | pix;
-	}
-      }
-      ++lp;
-    }
-    *(lp - 1) <<= lbpl * 8 - lx;
-    hp1 += hbpl;
-    hp2 += hbpl;
-    hp3 += hbpl;
-  }
-
-#ifdef DEBUG
-  {
-    FILE *f;
-    char fn[50];
-    
-    sprintf(fn, "dbg_d=%02d.pbm", higher_layer - 1);
-    f = fopen(fn, "wb");
-    fprintf(f, "P4\n%lu %lu\n", lx, ly);
-    fwrite(s->lhp[1 - s->highres[plane]][plane], 1, lbpl * ly, f);
-    fclose(f);
-  }
-#endif
-
-  return;
-}
-
-
-/* 
- * This function is called inside the three loops of jbg_enc_out() in
- * order to write the next SDE. It has first to generate the required
- * SDE and all SDEs which have to be encoded before this SDE can be
- * created. The problem here is that if we want to output a lower
- * resolution layer, we have to allpy the resolution reduction
- * algorithm in order to get it. As we try to safe as much memory as
- * possible, the resolution reduction will overwrite previous higher
- * resolution bitmaps. Consequently, we have to encode and buffer SDEs
- * which depend on higher resolution layers before we can start the
- * resolution reduction. All this logic about which SDE has to be
- * encoded before resolution reduction is allowed is handled here.
- * This approach might be a little bit more complex than alternative
- * ways to do it, but it allows us to do the encoding with the minimal
- * possible amount of temporary memory.
- */
-static void output_sde(struct jbg_enc_state *s,
-		       unsigned long stripe, int layer, int plane)
-{
-  int lfcl;     /* lowest fully coded layer */
-  long i;
-  unsigned long u;
-  
-  assert(s->sde[stripe][layer][plane] != SDE_DONE);
-
-  if (s->sde[stripe][layer][plane] != SDE_TODO) {
-#ifdef DEBUG
-    fprintf(stderr, "writing SDE: s/d/p = %2lu/%2d/%2d\n",
-	    stripe, layer, plane);
-#endif
-    jbg_buf_output(&s->sde[stripe][layer][plane], s->data_out, s->file);
-    s->sde[stripe][layer][plane] = SDE_DONE;
-    return;
-  }
-
-  /* Determine the smallest resolution layer in this plane for which
-   * not yet all stripes have been encoded into SDEs. This layer will
-   * have to be completely coded, before we can apply the next
-   * resolution reduction step. */
-  lfcl = 0;
-  for (i = s->d; i >= 0; i--)
-    if (s->sde[s->stripes - 1][i][plane] == SDE_TODO) {
-      lfcl = i + 1;
-      break;
-    }
-  if (lfcl > s->d && s->d > 0 && stripe == 0) {
-    /* perform the first resolution reduction */
-    resolution_reduction(s, plane, s->d);
-  }
-  /* In case HITOLO is not used, we have to encode and store the higher
-   * resolution layers first, although we do not need them right now. */
-  while (lfcl - 1 > layer) {
-    for (u = 0; u < s->stripes; u++)
-      encode_sde(s, u, lfcl - 1, plane);
-    --lfcl;
-    s->highres[plane] ^= 1;
-    if (lfcl > 1)
-      resolution_reduction(s, plane, lfcl - 1);
-  }
-  
-  encode_sde(s, stripe, layer, plane);
-
-#ifdef DEBUG
-  fprintf(stderr, "writing SDE: s/d/p = %2lu/%2d/%2d\n", stripe, layer, plane);
-#endif
-  jbg_buf_output(&s->sde[stripe][layer][plane], s->data_out, s->file);
-  s->sde[stripe][layer][plane] = SDE_DONE;
-  
-  if (stripe == s->stripes - 1 && layer > 0 &&
-      s->sde[0][layer-1][plane] == SDE_TODO) {
-    s->highres[plane] ^= 1;
-    if (layer > 1)
-      resolution_reduction(s, plane, layer - 1);
-  }
-  
-  return;
-}
-
-
-/*
- * Convert the table which controls the deterministic prediction
- * process from the internal format into the representation required
- * for the 1728 byte long DPTABLE element of a BIH.
- *
- * The bit order of the DPTABLE format (see also ITU-T T.82 figure 13) is
- *
- * high res:   4  5  6     low res:  0  1
- *             7  8  9               2  3
- *            10 11 12
- *
- * were 4 table entries are packed into one byte, while we here use
- * internally an unpacked 6912 byte long table indexed by the following
- * bit order:
- *
- * high res:   7  6  5     high res:   8  7  6     low res:  1  0
- * (phase 0)   4  .  .     (phase 1)   5  4  .               3  2
- *             .  .  .                 .  .  .
- *
- * high res:  10  9  8     high res:  11 10  9
- * (phase 2)   7  6  5     (phase 3)   8  7  6
- *             4  .  .                 5  4  .
- */
-void jbg_int2dppriv(unsigned char *dptable, const char *internal)
-{
-  int i, j, k;
-  int trans0[ 8] = { 1, 0, 3, 2, 7, 6, 5, 4 };
-  int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 };
-  int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 };
-  int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 };
-  
-  for (i = 0; i < 1728; dptable[i++] = 0);
-
-#define FILL_TABLE1(offset, len, trans) \
-  for (i = 0; i < len; i++) { \
-    k = 0; \
-    for (j = 0; j < 8; j++) \
-      k |= ((i >> j) & 1) << trans[j]; \
-    dptable[(i + offset) >> 2] |= \
-      (internal[k + offset] & 3) << ((3 - (i&3)) << 1); \
-  }
-
-  FILL_TABLE1(   0,  256, trans0);
-  FILL_TABLE1( 256,  512, trans1);
-  FILL_TABLE1( 768, 2048, trans2);
-  FILL_TABLE1(2816, 4096, trans3);
-
-  return;
-}
-
-
-/*
- * Convert the table which controls the deterministic prediction
- * process from the 1728 byte long DPTABLE format into the 6912 byte long
- * internal format.
- */
-void jbg_dppriv2int(char *internal, const unsigned char *dptable)
-{
-  int i, j, k;
-  int trans0[ 8] = { 1, 0, 3, 2, 7, 6, 5, 4 };
-  int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 };
-  int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 };
-  int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 };
-  
-#define FILL_TABLE2(offset, len, trans) \
-  for (i = 0; i < len; i++) { \
-    k = 0; \
-    for (j = 0; j < 8; j++) \
-      k |= ((i >> j) & 1) << trans[j]; \
-    internal[k + offset] = \
-      (dptable[(i + offset) >> 2] >> ((3 - (i & 3)) << 1)) & 3; \
-  }
-
-  FILL_TABLE2(   0,  256, trans0);
-  FILL_TABLE2( 256,  512, trans1);
-  FILL_TABLE2( 768, 2048, trans2);
-  FILL_TABLE2(2816, 4096, trans3);
-
-  return;
-}
-
-
-/*
- * Encode one full BIE and pass the generated data to the specified
- * call-back function
- */
-void jbg_enc_out(struct jbg_enc_state *s)
-{
-  long bpl;
-  unsigned char bih[20];
-  unsigned long xd, yd, y;
-  long ii[3], is[3], ie[3];    /* generic variables for the 3 nested loops */ 
-  unsigned long stripe;
-  int layer, plane;
-  int order;
-  unsigned char dpbuf[1728];
-  extern char jbg_dptable[];
-
-  /* some sanity checks */
-  s->order &= JBG_HITOLO | JBG_SEQ | JBG_ILEAVE | JBG_SMID;
-  order = s->order & (JBG_SEQ | JBG_ILEAVE | JBG_SMID);
-  if (index[order][0] < 0)
-    s->order = order = JBG_SMID | JBG_ILEAVE;
-  if (s->options & JBG_DPON && s->dppriv != jbg_dptable)
-    s->options |= JBG_DPPRIV;
-  if (s->mx > MX_MAX)
-    s->mx = MX_MAX;
-  s->my = 0;
-  if (s->mx && s->mx < ((s->options & JBG_LRLTWO) ? 5U : 3U))
-    s->mx = 0;
-  if (s->d > 255 || s->d < 0 || s->dh > s->d || s->dh < 0 ||
-      s->dl < 0 || s->dl > s->dh || s->planes < 0 || s->planes > 255)
-    return;
-
-  /* ensure correct zero padding of bitmap at the final byte of each line */
-  if (s->xd & 7) {
-    bpl = (s->xd + 7) / 8;     /* bytes per line */
-    for (plane = 0; plane < s->planes; plane++)
-      for (y = 0; y < s->yd; y++)
-	s->lhp[0][plane][y * bpl + bpl - 1] &= ~((1 << (8 - (s->xd & 7))) - 1);
-  }
-
-  /* calculate number of stripes that will be required */
-  s->stripes = ((s->yd >> s->d) + 
-		((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0;
-
-  /* allocate buffers for SDE pointers */
-  if (s->sde == NULL) {
-    s->sde = (struct jbg_buf ****)
-      checked_malloc(s->stripes * sizeof(struct jbg_buf ***));
-    for (stripe = 0; stripe < s->stripes; stripe++) {
-      s->sde[stripe] = (struct jbg_buf ***)
-	checked_malloc((s->d + 1) * sizeof(struct jbg_buf **));
-      for (layer = 0; layer < s->d + 1; layer++) {
-	s->sde[stripe][layer] = (struct jbg_buf **)
-	  checked_malloc(s->planes * sizeof(struct jbg_buf *));
-	for (plane = 0; plane < s->planes; plane++)
-	  s->sde[stripe][layer][plane] = SDE_TODO;
-      }
-    }
-  }
-
-  /* output BIH */
-  bih[0] = s->dl;
-  bih[1] = s->dh;
-  bih[2] = s->planes;
-  bih[3] = 0;
-  xd = jbg_ceil_half(s->xd, s->d - s->dh);
-  yd = jbg_ceil_half(s->yd, s->d - s->dh);
-  bih[4] = xd >> 24;
-  bih[5] = (xd >> 16) & 0xff;
-  bih[6] = (xd >> 8) & 0xff;
-  bih[7] = xd & 0xff;
-  bih[8] = yd >> 24;
-  bih[9] = (yd >> 16) & 0xff;
-  bih[10] = (yd >> 8) & 0xff;
-  bih[11] = yd & 0xff;
-  bih[12] = s->l0 >> 24;
-  bih[13] = (s->l0 >> 16) & 0xff;
-  bih[14] = (s->l0 >> 8) & 0xff;
-  bih[15] = s->l0 & 0xff;
-  bih[16] = s->mx;
-  bih[17] = s->my;
-  bih[18] = s->order;
-  bih[19] = s->options & 0x7f;
-  s->data_out(bih, 20, s->file);
-  if ((s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) ==
-      (JBG_DPON | JBG_DPPRIV)) {
-    /* write private table */
-    jbg_int2dppriv(dpbuf, s->dppriv);
-    s->data_out(dpbuf, 1728, s->file);
-  }
-
-#if 0
-  /*
-   * Encode everything first. This is a simple-minded alternative to
-   * all the tricky on-demand encoding logic in output_sde() for
-   * debugging purposes.
-   */
-  for (layer = s->dh; layer >= s->dl; layer--) {
-    for (plane = 0; plane < s->planes; plane++) {
-      if (layer > 0)
-	resolution_reduction(s, plane, layer);
-      for (stripe = 0; stripe < s->stripes; stripe++)
-	encode_sde(s, stripe, layer, plane);
-      s->highres[plane] ^= 1;
-    }
-  }
-#endif
-
-  /*
-   * Generic loops over all SDEs. Which loop represents layer, plane and
-   * stripe depends on the option flags.
-   */
-
-  /* start and end value vor each loop */
-  is[index[order][STRIPE]] = 0;
-  ie[index[order][STRIPE]] = s->stripes - 1;
-  is[index[order][LAYER]] = s->dl;
-  ie[index[order][LAYER]] = s->dh;
-  is[index[order][PLANE]] = 0;
-  ie[index[order][PLANE]] = s->planes - 1;
-
-  for (ii[0] = is[0]; ii[0] <= ie[0]; ii[0]++)
-    for (ii[1] = is[1]; ii[1] <= ie[1]; ii[1]++)
-      for (ii[2] = is[2]; ii[2] <= ie[2]; ii[2]++) {
-	
-	stripe = ii[index[order][STRIPE]];
-	if (s->order & JBG_HITOLO)
-	  layer = s->dh - (ii[index[order][LAYER]] - s->dl);
-	else
-	  layer = ii[index[order][LAYER]];
-	plane = ii[index[order][PLANE]];
-
-	output_sde(s, stripe, layer, plane);
-
-      }
-
-  return;
-}
-
-
-void jbg_enc_free(struct jbg_enc_state *s)
-{
-  unsigned long stripe;
-  int layer, plane;
-
-#ifdef DEBUG
-  fprintf(stderr, "jbg_enc_free(%p)\n", s);
-#endif
-
-  /* clear buffers for SDEs */
-  if (s->sde) {
-    for (stripe = 0; stripe < s->stripes; stripe++) {
-      for (layer = 0; layer < s->d + 1; layer++) {
-	for (plane = 0; plane < s->planes; plane++)
-	  if (s->sde[stripe][layer][plane] != SDE_DONE &&
-	      s->sde[stripe][layer][plane] != SDE_TODO)
-	    jbg_buf_free(&s->sde[stripe][layer][plane]);
-	checked_free(s->sde[stripe][layer]);
-      }
-      checked_free(s->sde[stripe]);
-    }
-    checked_free(s->sde);
-  }
-
-  /* clear free_list */
-  jbg_buf_free(&s->free_list);
-
-  /* clear memory for arithmetic encoder states */
-  checked_free(s->s);
-
-  /* clear memory for differential-layer typical prediction buffer */
-  checked_free(s->tp);
-
-  /* clear memory for adaptive template pixel offsets */
-  checked_free(s->tx);
-
-  /* clear lowres image buffers */
-  if (s->lhp[1]) {
-    for (plane = 0; plane < s->planes; plane++)
-      checked_free(s->lhp[1][plane]);
-    checked_free(s->lhp[1]);
-  }
-
-  return;
-}
-
-
-/*
- * Convert the error codes used by jbg_dec_in() into a string
- * written in the selected language and character set.
- */
-const char *jbg_strerror(int errnum, int language)
-{
-  if (errnum < 0 || errnum >= NEMSG)
-    return "Unknown error code passed to jbg_strerror()";
-  if (language < 0 || language >= NEMSG_LANG)
-    return "Unknown language code passed to jbg_strerror()";
-
-  return errmsg[language][errnum];
-}
-
-
-/*
- * The constructor for a decoder 
- */
-void jbg_dec_init(struct jbg_dec_state *s)
-{
-  s->order = 0;
-  s->d = -1;
-  s->bie_len = 0;
-  s->buf_len = 0;
-  s->dppriv = NULL;
-  s->xmax = 4294967295UL;
-  s->ymax = 4294967295UL;
-  s->dmax = 256;
-  s->s = NULL;
-
-  return;
-}
-
-
-/*
- * Specify a maximum image size for the decoder. If the JBIG file has
- * the order bit ILEAVE, but not the bit SEQ set, then the decoder
- * will abort to decode after the image has reached the maximal
- * resolution layer which is still not wider than xmax or higher than
- * ymax.
- */
-void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax,
-		     unsigned long ymax)
-{
-  if (xmax > 0) s->xmax = xmax;
-  if (ymax > 0) s->ymax = ymax;
-
-  return;
-}
-
-
-/*
- * Decode the new len PSDC bytes to which data points and add them to
- * the current stripe. Return the number of bytes which have actually
- * been read (this will be less than len if a marker segment was 
- * part of the data or if the final byte was 0xff were this code
- * can not determine, whether we have a marker segment.
- */
-static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data,
-			  size_t len)
-{
-  unsigned long stripe;
-  unsigned int layer, plane;
-  unsigned long hl, ll, y, hx, hy, lx, ly, hbpl, lbpl;
-  unsigned char *hp, *lp1, *lp2, *p1, *q1;
-  register unsigned long line_h1, line_h2, line_h3;
-  register unsigned long line_l1, line_l2, line_l3;
-  struct jbg_ardec_state *se;
-  unsigned long x;
-  int n;
-  int pix, cx = 0, slntp, shift, tx;
-
-  /* SDE loop variables */
-  stripe = s->ii[index[s->order & 7][STRIPE]];
-  layer = s->ii[index[s->order & 7][LAYER]];
-  plane = s->ii[index[s->order & 7][PLANE]];
-
-  /* forward data to arithmetic decoder */
-  se = s->s[plane] + layer - s->dl;
-  se->pscd_ptr = data;
-  se->pscd_end = data + len;
-  
-  /* number of lines per stripe in highres image */
-  hl = s->l0 << layer;
-  /* number of lines per stripe in lowres image */
-  ll = hl >> 1;
-  /* current line number in highres image */
-  y = stripe * hl + s->i;
-  /* number of pixels in highres image */
-  hx = jbg_ceil_half(s->xd, s->d - layer);
-  hy = jbg_ceil_half(s->yd, s->d - layer);
-  /* number of pixels in lowres image */
-  lx = jbg_ceil_half(hx, 1);
-  ly = jbg_ceil_half(hy, 1);
-  /* bytes per line in highres and lowres image */
-  hbpl = (hx + 7) / 8;
-  lbpl = (lx + 7) / 8;
-  /* pointer to highres and lowres image bytes */
-  hp  = s->lhp[ layer    & 1][plane] + (stripe * hl + s->i) * hbpl +
-    (s->x >> 3);
-  lp2 = s->lhp[(layer-1) & 1][plane] + (stripe * ll + (s->i >> 1)) * lbpl +
-    (s->x >> 4);
-  lp1 = lp2 + lbpl;
-
-  /* restore a few local variables */
-  line_h1 = s->line_h1;
-  line_h2 = s->line_h2;
-  line_h3 = s->line_h3;
-  line_l1 = s->line_l1;
-  line_l2 = s->line_l2;
-  line_l3 = s->line_l3;
-  x = s->x;
-
-  if (s->x == 0 && s->i == 0 &&
-      (stripe == 0 || s->reset[plane][layer - s->dl])) {
-    s->tx[plane][layer - s->dl] = s->ty[plane][layer - s->dl] = 0;
-    if (s->pseudo)
-      s->lntp[plane][layer - s->dl] = 1;
-  }
-
-#ifdef DEBUG
-  if (s->x == 0 && s->i == 0 && s->pseudo)
-    fprintf(stderr, "decode_pscd(%p, %p, %ld): s/d/p = %2lu/%2u/%2u\n",
-	    s, data, (long) len, stripe, layer, plane);
-#endif
-
-  if (layer == 0) {
-
-    /*
-     *  Decode lowest resolution layer
-     */
-
-    for (; s->i < hl && y < hy; s->i++, y++) {
-
-      /* adaptive template changes */
-      if (x == 0)
-	for (n = 0; n < s->at_moves; n++)
-	  if (s->at_line[n] == s->i) {
-	    s->tx[plane][layer - s->dl] = s->at_tx[n];
-	    s->ty[plane][layer - s->dl] = s->at_ty[n];
-#ifdef DEBUG
-	    fprintf(stderr, "ATMOVE: line=%lu, tx=%d, ty=%d.\n", s->i,
-		    s->tx[plane][layer - s->dl], s->ty[plane][layer - s->dl]);
-#endif
-	  }
-      tx = s->tx[plane][layer - s->dl];
-      shift =  tx - ((s->options & JBG_LRLTWO) ? 5 : 3);
-
-      /* typical prediction */
-      if (s->options & JBG_TPBON && s->pseudo) {
-	slntp = arith_decode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX);
-	if (se->result == JBG_MORE || se->result == JBG_MARKER)
-	  goto leave;
-	s->lntp[plane][layer - s->dl] =
-	  !(slntp ^ s->lntp[plane][layer - s->dl]);
-	if (s->lntp[plane][layer - s->dl]) {
-	  /* this line is 'not typical' and has to be coded completely */
-	  s->pseudo = 0;
-	} else {
-	  /* this line is 'typical' (i.e. identical to the previous one) */
-	  p1 = hp;
-	  if (s->i == 0 && (stripe == 0 || s->reset[plane][layer - s->dl]))
-	    while (p1 < hp + hbpl) *p1++ = 0;
-	  else {
-	    q1 = hp - hbpl;
-	    while (q1 < hp) *p1++ = *q1++;
-	  }
-	  hp += hbpl;
-	  continue;
-	}
-      }
-      
-      /*
-       * Layout of the variables line_h1, line_h2, line_h3, which contain
-       * as bits the neighbour pixels of the currently decoded pixel X:
-       *
-       *                     76543210 76543210 76543210 76543210     line_h3
-       *                     76543210 76543210 76543210 76543210     line_h2
-       *   76543210 76543210 76543210 76543210 X                     line_h1
-       */
-      
-      if (x == 0) {
-	line_h1 = line_h2 = line_h3 = 0;
-	if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl]))
-	  line_h2 = (long)*(hp - hbpl) << 8;
-	if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl]))
-	  line_h3 = (long)*(hp - hbpl - hbpl) << 8;
-      }
-      
-      /*
-       * Another tiny JBIG standard bug:
-       *
-       * While implementing the line_h3 handling here, I discovered
-       * another problem with the ITU-T T.82(1993 E) specification.
-       * This might be a somewhat pathological case, however. The
-       * standard is unclear about how a decoder should behave in the
-       * following situation:
-       *
-       * Assume we are in layer 0 and all stripes are single lines
-       * (L0=1 allowed by table 9). We are now decoding the first (and
-       * only) line of the third stripe. Assume, the first stripe was
-       * terminated by SDRST and the second stripe was terminated by
-       * SDNORM. While decoding the only line of the third stripe with
-       * the three-line template, we need access to pixels from the
-       * previous two stripes. We know that the previous stripe
-       * terminated with SDNROM, so we access the pixel from the
-       * second stripe. But do we have to replace the pixels from the
-       * first stripe by background pixels, because this stripe ended
-       * with SDRST? The standard, especially clause 6.2.5 does never
-       * mention this case, so the behaviour is undefined here. My
-       * current implementation remembers only the marker used to
-       * terminate the previous stripe. In the above example, the
-       * pixels of the first stripe are accessed despite the fact that
-       * this stripe ended with SDRST. An alternative (only slightly
-       * more complicated) implementation would be to remember the end
-       * marker (SDNORM or SDRST) of the previous two stripes in a
-       * plane/layer and to act accordingly when accessing the two
-       * previous lines. What am I supposed to do here?
-       *
-       * As the standard is unclear about the correct behaviour in the
-       * situation of the above example, I strongly suggest to avoid
-       * the following situation while encoding data with JBIG:
-       *
-       *   LRLTWO = 0, L0=1 and both SDNORM and SDRST appear in layer 0.
-       *
-       * I guess that only a very few if any encoders will switch
-       * between SDNORM and SDRST, so let us hope that this ambiguity
-       * in the standard will never cause any interoperability
-       * problems.
-       *
-       * Markus Kuhn -- 1995-04-30
-       */
-
-      /* decode line */
-      while (x < hx) {
-	if ((x & 7) == 0) {
-	  if (x < hbpl * 8 - 8 &&
-	      (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl]))) {
-	    line_h2 |= *(hp - hbpl + 1);
-	    if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl]))
-	      line_h3 |= *(hp - hbpl - hbpl + 1);
-	  }
-	}
-	if (s->options & JBG_LRLTWO) {
-	  /* two line template */
-	  do {
-	    if (tx)
-	      pix = arith_decode(se, (((line_h2 >> 9) & 0x3e0) |
-				      ((line_h1 >> shift) & 0x010) |
-				      (line_h1 & 0x00f)));
-	    else
-	      pix = arith_decode(se, (((line_h2 >> 9) & 0x3f0) |
-				      (line_h1 & 0x00f)));
-	    if (se->result == JBG_MORE || se->result == JBG_MARKER)
-	      goto leave;
-	    line_h1 = (line_h1 << 1) | pix;
-	    line_h2 <<= 1;
-	  } while ((++x & 7) && x < hx);
-	} else {
-	  /* three line template */
-	  do {
-	    if (tx) 
-	      pix = arith_decode(se, (((line_h3 >>  7) & 0x380) |
-				      ((line_h2 >> 11) & 0x078) |
-				      ((line_h1 >> shift) & 0x004) |
-				      (line_h1 & 0x003)));
-	    else
-	      pix = arith_decode(se, (((line_h3 >>  7) & 0x380) |
-				      ((line_h2 >> 11) & 0x07c) |
-				      (line_h1 & 0x003)));
-	    if (se->result == JBG_MORE || se->result == JBG_MARKER)
-	      goto leave;
-	    
-	    line_h1 = (line_h1 << 1) | pix;
-	    line_h2 <<= 1;
-	    line_h3 <<= 1;
-	  } while ((++x & 7) && x < hx);
-	} /* if (s->options & JBG_LRLTWO) */
-	*hp++ = line_h1;
-      } /* while */
-      *(hp - 1) <<= hbpl * 8 - hx;
-      x = 0;
-      s->pseudo = 1;
-    } /* for (i = ...) */
-    
-  } else {
-
-    /*
-     *  Decode differential layer
-     */
-
-    for (; s->i < hl && y < hy; s->i++, y++) {
-
-      /* adaptive template changes */
-      if (x == 0)
-	for (n = 0; n < s->at_moves; n++)
-	  if (s->at_line[n] == s->i) {
-	    s->tx[plane][layer - s->dl] = s->at_tx[n];
-	    s->ty[plane][layer - s->dl] = s->at_ty[n];
-#ifdef DEBUG
-	    fprintf(stderr, "ATMOVE: line=%lu, tx=%d, ty=%d.\n", s->i,
-		    s->tx[plane][layer - s->dl], s->ty[plane][layer - s->dl]);
-#endif
-	  }
-      tx = s->tx[plane][layer - s->dl];
-      shift = tx - 3;
-
-      /* handle lower border of low-resolution image */
-      if ((s->i >> 1) >= ll - 1 || (y >> 1) >= ly - 1)
-	lp1 = lp2;
-
-      /* typical prediction */
-      if (s->options & JBG_TPDON && s->pseudo) {
-	s->lntp[plane][layer - s->dl] = arith_decode(se, TPDCX);
-	if (se->result == JBG_MORE || se->result == JBG_MARKER)
-	  goto leave;
-	s->pseudo = 0;
-      }
-
-
-      /*
-       * Layout of the variables line_h1, line_h2, line_h3, which contain
-       * as bits the high resolution neighbour pixels of the currently
-       * decoded highres pixel X:
-       *
-       *                     76543210 76543210 76543210 76543210     line_h3
-       *                     76543210 76543210 76543210 76543210     line_h2
-       *   76543210 76543210 76543210 76543210 X                     line_h1
-       *
-       * Layout of the variables line_l1, line_l2, line_l3, which contain
-       * the low resolution pixels near the currently decoded pixel as bits.
-       * The lowres pixel in which the currently coded highres pixel is
-       * located is marked as Y:
-       *
-       *                     76543210 76543210 76543210 76543210     line_l3
-       *                     76543210 76543210 Y6543210 76543210     line_l2
-       *                     76543210 76543210 76543210 76543210     line_l1
-       */
-      
-
-      if (x == 0) {
-	line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0;
-	if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) {
-	  line_h2 = (long)*(hp - hbpl) << 8;
-	  if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl]))
-	    line_h3 = (long)*(hp - hbpl - hbpl) << 8;
-	}
-	if (s->i > 1 || (y > 1 && !s->reset[plane][layer-s->dl]))
-	  line_l3 = (long)*(lp2 - lbpl) << 8;
-	line_l2 = (long)*lp2 << 8;
-	line_l1 = (long)*lp1 << 8;
-      }
-      
-      /* decode line */
-      while (x < hx) {
-	if ((x & 15) == 0)
-	  if ((x >> 1) < lbpl * 8 - 8) {
-	    line_l1 |= *(lp1 + 1);
-	    line_l2 |= *(lp2 + 1);
-	    if (s->i > 1 || 
-		(y > 1 && !s->reset[plane][layer - s->dl]))
-	      line_l3 |= *(lp2 - lbpl + 1);
-	  }
-	do {
-
-	  assert(hp  - (s->lhp[ layer     &1][plane] + (stripe * hl + s->i)
-			* hbpl) == (ptrdiff_t) x >> 3);
-	  assert(lp2 - (s->lhp[(layer-1) &1][plane] + (stripe * ll + (s->i>>1))
-			* lbpl) == (ptrdiff_t) x >> 4);
-
-	  if ((x & 7) == 0)
-	    if (x < hbpl * 8 - 8) {
-	      if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) {
-		line_h2 |= *(hp + 1 - hbpl);
-		if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl]))
-		  line_h3 |= *(hp + 1 - hbpl - hbpl);
-	      }
-	    }
-	  do {
-	    if (!s->lntp[plane][layer - s->dl])
-              cx = (((line_l3 >> 14) & 0x007) |
-                    ((line_l2 >> 11) & 0x038) |
-                    ((line_l1 >> 8)  & 0x1c0));
-	    if (!s->lntp[plane][layer - s->dl] &&
-		(cx == 0x000 || cx == 0x1ff)) {
-	      /* pixels are typical and have not to be decoded */
-	      do {
-		line_h1 = (line_h1 << 1) | (cx & 1);
-	      } while ((++x & 1) && x < hx);
-	      line_h2 <<= 2;  line_h3 <<= 2;
-	    } else 
-	      do {
-		
-		/* deterministic prediction */
-		if (s->options & JBG_DPON)
-		  if ((y & 1) == 0)
-		    if ((x & 1) == 0) 
-		      /* phase 0 */
-		      pix = s->dppriv[((line_l3 >> 15) & 0x003) |
-				      ((line_l2 >> 13) & 0x00c) |
-				      ((line_h1 <<  4) & 0x010) |
-				      ((line_h2 >>  9) & 0x0e0)];
-		    else
-		      /* phase 1 */
-		      pix = s->dppriv[(((line_l3 >> 15) & 0x003) |
-				       ((line_l2 >> 13) & 0x00c) |
-				       ((line_h1 <<  4) & 0x030) |
-				       ((line_h2 >>  9) & 0x1c0)) + 256];
-		  else
-		    if ((x & 1) == 0)
-		      /* phase 2 */
-		      pix = s->dppriv[(((line_l3 >> 15) & 0x003) |
-				       ((line_l2 >> 13) & 0x00c) |
-				       ((line_h1 <<  4) & 0x010) |
-				       ((line_h2 >>  9) & 0x0e0) |
-				       ((line_h3 >>  6) & 0x700)) + 768];
-		    else
-		      /* phase 3 */
-		      pix = s->dppriv[(((line_l3 >> 15) & 0x003) |
-				       ((line_l2 >> 13) & 0x00c) |
-				       ((line_h1 <<  4) & 0x030) |
-				       ((line_h2 >>  9) & 0x1c0) |
-				       ((line_h3 >>  6) & 0xe00)) + 2816];
-		else
-		  pix = 2;
-
-		if (pix & 2) {
-		  if (tx)
-		    cx = ((line_h1         & 0x003) |
-			  (((line_h1 << 2) >> shift) & 0x010) |
-			  ((line_h2 >> 12) & 0x00c) |
-			  ((line_h3 >> 10) & 0x020));
-		  else
-		    cx = ((line_h1         & 0x003) |
-			  ((line_h2 >> 12) & 0x01c) |
-			  ((line_h3 >> 10) & 0x020));
-		  if (x & 1)
-		    cx |= (((line_l2 >> 8) & 0x0c0) |
-			   ((line_l1 >> 6) & 0x300)) | (1UL << 10);
-		  else
-		    cx |= (((line_l2 >> 9) & 0x0c0) |
-			   ((line_l1 >> 7) & 0x300));
-		  cx |= (y & 1) << 11;
-
-		  pix = arith_decode(se, cx);
-		  if (se->result == JBG_MORE || se->result == JBG_MARKER)
-		    goto leave;
-		}
-
-		line_h1 = (line_h1 << 1) | pix;
-		line_h2 <<= 1;
-		line_h3 <<= 1;
-		
-	      } while ((++x & 1) && x < hx);
-	    line_l1 <<= 1; line_l2 <<= 1;  line_l3 <<= 1;
-	  } while ((x & 7) && x < hx);
-	  *hp++ = line_h1;
-	} while ((x & 15) && x < hx);
-	++lp1;
-	++lp2;
-      } /* while */
-      x = 0;
-      
-      *(hp - 1) <<= hbpl * 8 - hx;
-      if ((s->i & 1) == 0) {
-	/* low resolution pixels are used twice */
-	lp1 -= lbpl;
-	lp2 -= lbpl;
-      } else
-	s->pseudo = 1;
-      
-    } /* for (i = ...) */
-    
-  }
-
- leave:
-
-  /* save a few local variables */
-  s->line_h1 = line_h1;
-  s->line_h2 = line_h2;
-  s->line_h3 = line_h3;
-  s->line_l1 = line_l1;
-  s->line_l2 = line_l2;
-  s->line_l3 = line_l3;
-  s->x = x;
-
-  return se->pscd_ptr - data;
-}
-
-
-/*
- * Provide a new BIE fragment to the decoder.
- *
- * If cnt is not NULL, then *cnt will contain after the call the
- * number of actually read bytes. If the data was not complete, then
- * the return value will be JBG_EAGAIN and *cnt == len. In case this
- * function has returned with JBG_EOK, then it has reached the end of
- * a BIE but it can be called again with data from the next BIE if
- * there exists one in order to get to a higher resolution layer. In
- * case the return value was JBG_EOK_INTR then this function can be
- * called again with the rest of the BIE, because parsing the BIE has
- * been interrupted by a jbg_dec_maxsize() specification. In both
- * cases the remaining len - *cnt bytes of the previous block will
- * have to passed to this function again (if len > *cnt). In case of
- * any other return value than JBG_EOK, JBG_EOK_INTR or JBG_EAGAIN, a
- * serious problem has occurred and the only function you should call
- * is jbg_dec_free() in order to remove the mess (and probably
- * jbg_strerror() in order to find out what to tell the user).
- */
-int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len,
-	       size_t *cnt)
-{
-  int i, j, required_length;
-  unsigned long x, y;
-  unsigned long is[3], ie[3];
-  long hsize, lsize;
-  extern char jbg_dptable[];
-  size_t dummy_cnt;
-
-  if (!cnt) cnt = &dummy_cnt;
-  *cnt = 0;
-  if (len < 1) return JBG_EAGAIN;
-
-  /* read in 20-byte BIH */
-  if (s->bie_len < 20) {
-    while (s->bie_len < 20 && *cnt < len)
-      s->buffer[s->bie_len++] = data[(*cnt)++];
-    if (s->bie_len < 20) 
-      return JBG_EAGAIN;
-    if (s->buffer[1] < s->buffer[0])
-      return JBG_EINVAL;
-    /* test whether this looks like a valid JBIG header at all */
-    if (s->buffer[3] != 0 || (s->buffer[18] & 0xf0) != 0 ||
-	(s->buffer[19] & 0x80) != 0)
-      return JBG_EINVAL;
-    if (s->buffer[0] != s->d + 1)
-      return JBG_ENOCONT;
-    s->dl = s->buffer[0];
-    s->d = s->buffer[1];
-    if (s->dl == 0)
-      s->planes = s->buffer[2];
-    else
-      if (s->planes != s->buffer[2])
-	return JBG_ENOCONT;
-    x = (((long) s->buffer[ 4] << 24) | ((long) s->buffer[ 5] << 16) |
-	 ((long) s->buffer[ 6] <<  8) | (long) s->buffer[ 7]);
-    y = (((long) s->buffer[ 8] << 24) | ((long) s->buffer[ 9] << 16) |
-	 ((long) s->buffer[10] <<  8) | (long) s->buffer[11]);
-    if (s->dl != 0 && ((s->xd << (s->d - s->dl + 1)) != x &&
-		       (s->yd << (s->d - s->dl + 1)) != y))
-      return JBG_ENOCONT;
-    s->xd = x;
-    s->yd = y;
-    s->l0 = (((long) s->buffer[12] << 24) | ((long) s->buffer[13] << 16) |
-	     ((long) s->buffer[14] <<  8) | (long) s->buffer[15]);
-    if (!s->planes || !s->xd || !s->yd || !s->l0)
-      return JBG_EINVAL;
-    s->mx = s->buffer[16];
-    if (s->mx > 127)
-      return JBG_EINVAL;
-    s->my = s->buffer[17];
-    if (s->mx > 32 || s->my > 0) 
-      return JBG_EIMPL;
-    s->order = s->buffer[18];
-    if (index[s->order & 7][0] < 0)
-      return JBG_EINVAL;
-    /* HITOLO and SEQ currently not yet implemented */
-    if (s->dl != s->d && (s->order & JBG_HITOLO || s->order & JBG_SEQ))
-      return JBG_EIMPL;
-    s->options = s->buffer[19];
-
-    /* calculate number of stripes that will be required */
-    s->stripes = ((s->yd >> s->d) +
-		  ((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0;
-
-    /* some initialization */
-    s->ii[index[s->order & 7][STRIPE]] = 0;
-    s->ii[index[s->order & 7][LAYER]] = s->dl;
-    s->ii[index[s->order & 7][PLANE]] = 0;
-    /* bytes required for resolution layer D and D-1 */
-    hsize = ((s->xd + 7) / 8) * s->yd;
-    lsize = ((jbg_ceil_half(s->xd, 1) + 7) / 8) *
-      jbg_ceil_half(s->yd, 1);
-    if (s->dl == 0) {
-      s->s = checked_malloc(s->planes * sizeof(struct jbg_ardec_state *));
-      s->tx = checked_malloc(s->planes * sizeof(int *));
-      s->ty = checked_malloc(s->planes * sizeof(int *));
-      s->reset = checked_malloc(s->planes * sizeof(int *));
-      s->lntp = checked_malloc(s->planes * sizeof(int *));
-      s->lhp[0] = checked_malloc(s->planes * sizeof(unsigned char *));
-      s->lhp[1] = checked_malloc(s->planes * sizeof(unsigned char *));
-      for (i = 0; i < s->planes; i++) {
-	s->s[i] = checked_malloc((s->d - s->dl + 1) *
-				 sizeof(struct jbg_ardec_state));
-	s->tx[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int));
-	s->ty[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int));
-	s->reset[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int));
-	s->lntp[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int));
-	s->lhp[s->d    &1][i] = checked_malloc(sizeof(unsigned char) * hsize);
-	s->lhp[(s->d-1)&1][i] = checked_malloc(sizeof(unsigned char) * lsize);
-      }
-    } else {
-      for (i = 0; i < s->planes; i++) {
-	s->s[i] = checked_realloc(s->s[i], (s->d - s->dl + 1) *
-				  sizeof(struct jbg_ardec_state));
-	s->tx[i] = checked_realloc(s->tx[i], (s->d - s->dl + 1) * sizeof(int));
-	s->ty[i] = checked_realloc(s->ty[i], (s->d - s->dl + 1) * sizeof(int));
-	s->reset[i] = checked_realloc(s->reset[i],
-				      (s->d - s->dl +1) * sizeof(int));
-	s->lntp[i] = checked_realloc(s->lntp[i],
-				     (s->d - s->dl +1) * sizeof(int));
-	s->lhp[s->d    &1][i] = checked_realloc(s->lhp[s->d    & 1][i],
-						sizeof(unsigned char) * hsize);
-	s->lhp[(s->d-1)&1][i] = checked_realloc(s->lhp[(s->d-1)&1][i],
-						sizeof(unsigned char) * lsize);
-      }
-    }
-    for (i = 0; i < s->planes; i++)
-      for (j = 0; j <= s->d - s->dl; j++)
-	arith_decode_init(s->s[i] + j, 0);
-    if (s->dl == 0 || (s->options & JBG_DPON && !(s->options & JBG_DPPRIV)))
-      s->dppriv = jbg_dptable;
-    s->comment_skip = 0;
-    s->buf_len = 0;
-    s->x = 0;
-    s->i = 0;
-    s->pseudo = 1;
-    s->at_moves = 0;
-  }
-
-  /* read in DPTABLE */
-  if (s->bie_len < 20 + 1728 && 
-      (s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) ==
-      (JBG_DPON | JBG_DPPRIV)) {
-    assert(s->bie_len >= 20);
-    while (s->bie_len < 20 + 1728 && *cnt < len)
-      s->buffer[s->bie_len++ - 20] = data[(*cnt)++];
-    if (s->bie_len < 20 + 1728) 
-      return JBG_EAGAIN;
-    if (!s->dppriv || s->dppriv == jbg_dptable)
-      s->dppriv = checked_malloc(sizeof(char) * 1728);
-    jbg_dppriv2int(s->dppriv, s->buffer);
-  }
-
-  /*
-   * BID processing loop
-   */
-  
-  while (*cnt < len) {
-
-    /* process floating marker segments */
-
-    /* skip COMMENT contents */
-    if (s->comment_skip) {
-      if (s->comment_skip <= len - *cnt) {
-	*cnt += s->comment_skip;
-	s->comment_skip = 0;
-      } else {
-	s->comment_skip -= len - *cnt;
-	*cnt = len;
-      }
-      continue;
-    }
-
-    /* load complete marker segments into s->buffer for processing */
-    if (s->buf_len > 0) {
-      assert(s->buffer[0] == MARKER_ESC);
-      while (s->buf_len < 2 && *cnt < len)
-	s->buffer[s->buf_len++] = data[(*cnt)++];
-      if (s->buf_len < 2) continue;
-      switch (s->buffer[1]) {
-      case MARKER_COMMENT: required_length = 6; break;
-      case MARKER_ATMOVE:  required_length = 8; break;
-      case MARKER_NEWLEN:  required_length = 6; break;
-      case MARKER_ABORT:
-      case MARKER_SDNORM:
-      case MARKER_SDRST:   required_length = 2; break;
-      case MARKER_STUFF:
-	/* forward stuffed 0xff to arithmetic decoder */
-	s->buf_len = 0;
-	decode_pscd(s, s->buffer, 2);
-	continue;
-      default:
-	return JBG_EMARKER;
-      }
-      while (s->buf_len < required_length && *cnt < len)
-	s->buffer[s->buf_len++] = data[(*cnt)++];
-      if (s->buf_len < required_length) continue;
-      /* now the buffer is filled with exactly one marker segment */
-      switch (s->buffer[1]) {
-      case MARKER_COMMENT:
-	s->comment_skip = 
-	  (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) |
-	   ((long) s->buffer[4] <<  8) | (long) s->buffer[5]);
-	break;
-      case MARKER_ATMOVE:
-	if (s->at_moves < JBG_ATMOVES_MAX) {
-	  s->at_line[s->at_moves] =
-	    (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) |
-	     ((long) s->buffer[4] <<  8) | (long) s->buffer[5]);
-	  s->at_tx[s->at_moves] = (signed char) s->buffer[6];
-	  s->at_ty[s->at_moves] = s->buffer[7];
-	  if (s->at_tx[s->at_moves] < - (int) s->mx ||
-	      s->at_tx[s->at_moves] >   (int) s->mx ||
-	      s->at_ty[s->at_moves] >   (int) s->my ||
-	      (s->at_ty[s->at_moves] == 0 && s->at_tx[s->at_moves] < 0))
-	    return JBG_EINVAL;
-	  s->at_moves++;
-	} else
-	  return JBG_EINVAL;
-	break;
-      case MARKER_NEWLEN:
-	y = (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) |
-	     ((long) s->buffer[4] <<  8) | (long) s->buffer[5]);
-	if (y > s->yd || !(s->options & JBG_VLENGTH))
-	  return JBG_EINVAL;
-	s->yd = y;
-	/* calculate again number of stripes that will be required */
-	s->stripes = 
-	  ((s->yd >> s->d) +
-	   ((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0;
-	break;
-      case MARKER_ABORT:
-	return JBG_EABORT;
-	
-      case MARKER_SDNORM:
-      case MARKER_SDRST:
-	/* decode final pixels based on trailing zero bytes */
-	decode_pscd(s, s->buffer, 2);
-
-	arith_decode_init(s->s[s->ii[index[s->order & 7][PLANE]]] + 
-			  s->ii[index[s->order & 7][LAYER]] - s->dl,
-			  s->ii[index[s->order & 7][STRIPE]] != s->stripes - 1
-			  && s->buffer[1] != MARKER_SDRST);
-	
-	s->reset[s->ii[index[s->order & 7][PLANE]]]
-	  [s->ii[index[s->order & 7][LAYER]] - s->dl] =
-	    (s->buffer[1] == MARKER_SDRST);
-	
-	/* prepare for next SDE */
-	s->x = 0;
-	s->i = 0;
-	s->pseudo = 1;
-	s->at_moves = 0;
-	
-	/* increment layer/stripe/plane loop variables */
-	/* start and end value for each loop: */
-	is[index[s->order & 7][STRIPE]] = 0;
-	ie[index[s->order & 7][STRIPE]] = s->stripes - 1;
-	is[index[s->order & 7][LAYER]] = s->dl;
-	ie[index[s->order & 7][LAYER]] = s->d;
-	is[index[s->order & 7][PLANE]] = 0;
-	ie[index[s->order & 7][PLANE]] = s->planes - 1;
-	i = 2;  /* index to innermost loop */
-	do {
-	  j = 0;  /* carry flag */
-	  if (++s->ii[i] > ie[i]) {
-	    /* handling overflow of loop variable */
-	    j = 1;
-	    if (i > 0)
-	      s->ii[i] = is[i];
-	  }
-	} while (--i >= 0 && j);
-
-	s->buf_len = 0;
-	
-	/* check whether this have been all SDEs */
-	if (j) {
-	  s->bie_len = 0;
-	  return JBG_EOK;
-	}
-
-	/* check whether we have to abort because of xmax/ymax */
-	if (index[s->order & 7][LAYER] == 0 && i < 0) {
-	  /* LAYER is the outermost loop and we have just gone to next layer */
-	  if (jbg_ceil_half(s->xd, s->d - s->ii[0]) > s->xmax ||
-	      jbg_ceil_half(s->yd, s->d - s->ii[0]) > s->ymax) {
-	    s->xmax = 4294967295UL;
-	    s->ymax = 4294967295UL;
-	    return JBG_EOK_INTR;
-	  }
-	  if (s->ii[0] > (unsigned long) s->dmax) {
-	    s->dmax = 256;
-	    return JBG_EOK_INTR;
-	  }
-	}
-
-	break;
-      }
-      s->buf_len = 0;
-
-    } else if (data[*cnt] == MARKER_ESC)
-      s->buffer[s->buf_len++] = data[(*cnt)++];
-
-    else {
-
-      /* we have found PSCD bytes */
-      *cnt += decode_pscd(s, data + *cnt, len - *cnt);
-      if (*cnt < len && data[*cnt] != 0xff) {
-#ifdef DEBUG
-	fprintf(stderr, "PSCD was longer than expected, unread bytes "
-		"%02x %02x %02x %02x ...\n", data[*cnt], data[*cnt+1],
-		data[*cnt+2], data[*cnt+3]);
-#endif
-	return JBG_EINVAL;
-      }
-      
-    }
-  }  /* of BID processing loop 'while (*cnt < len) ...' */
-
-  return JBG_EAGAIN;
-}
-
-
-/*
- * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this
- * function in order to find out the width of the image.
- */
-long jbg_dec_getwidth(const struct jbg_dec_state *s)
-{
-  if (s->d < 0)
-    return -1;
-  if (index[s->order & 7][LAYER] == 0) {
-    if (s->ii[0] < 1)
-      return -1;
-    else
-      return jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1));
-  }
-
-  return s->xd;
-}
-
-
-/*
- * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this
- * function in order to find out the height of the image.
- */
-long jbg_dec_getheight(const struct jbg_dec_state *s)
-{
-  if (s->d < 0)
-    return -1;
-  if (index[s->order & 7][LAYER] == 0) {
-    if (s->ii[0] < 1)
-      return -1;
-    else
-      return jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1));
-  }
-  
-  return s->yd;
-}
-
-
-/*
- * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this
- * function in order to get a pointer to the image.
- */
-unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane)
-{
-  if (s->d < 0)
-    return NULL;
-  if (index[s->order & 7][LAYER] == 0) {
-    if (s->ii[0] < 1)
-      return NULL;
-    else
-      return s->lhp[(s->ii[0] - 1) & 1][plane];
-  }
-  
-  return s->lhp[s->d & 1][plane];
-}
-
-
-/*
- * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call
- * this function in order to find out the size in bytes of one
- * bitplane of the image.
- */
-long jbg_dec_getsize(const struct jbg_dec_state *s)
-{
-  if (s->d < 0)
-    return -1;
-  if (index[s->order & 7][LAYER] == 0) {
-    if (s->ii[0] < 1)
-      return -1;
-    else
-      return 
-	((jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) + 7) / 8) *
-	jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1));
-  }
-  
-  return ((s->xd + 7) / 8) * s->yd;
-}
-
-
-/*
- * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call
- * this function in order to find out the size of the image that you
- * can retrieve with jbg_merge_planes().
- */
-long jbg_dec_getsize_merged(const struct jbg_dec_state *s)
-{
-  if (s->d < 0)
-    return -1;
-  if (index[s->order & 7][LAYER] == 0) {
-    if (s->ii[0] < 1)
-      return -1;
-    else
-      return 
-	jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) *
-	jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)) *
-	((s->planes + 7) / 8);
-  }
-  
-  return s->xd * s->yd * ((s->planes + 7) / 8);
-}
-
-
-/* 
- * The destructor function which releases any resources obtained by the
- * other decoder functions.
- */
-void jbg_dec_free(struct jbg_dec_state *s)
-{
-  int i;
-
-  if (s->d < 0 || s->s == NULL)
-    return;
-  s->d = -2;
-
-  for (i = 0; i < s->planes; i++) {
-    checked_free(s->s[i]);
-    checked_free(s->tx[i]);
-    checked_free(s->ty[i]);
-    checked_free(s->reset[i]);
-    checked_free(s->lntp[i]);
-    checked_free(s->lhp[0][i]);
-    checked_free(s->lhp[1][i]);
-  }
-  
-  checked_free(s->s);
-  checked_free(s->tx);
-  checked_free(s->ty);
-  checked_free(s->reset);
-  checked_free(s->lntp);
-  checked_free(s->lhp[0]);
-  checked_free(s->lhp[1]);
-
-  s->s = NULL;
-
-  return;
-}
-
-
-/*
- * Split bigendian integer pixel field into separate bit planes. In the
- * src array, every pixel is represented by a ((has_planes + 7) / 8) byte
- * long word, most significant byte first. While has_planes describes
- * the number of used bits per pixel in the source image, encode_plane
- * is the number of most significant bits among those that we
- * actually transfer to dest.
- */
-void jbg_split_planes(unsigned long x, unsigned long y, int has_planes,
-		      int encode_planes,
-		      const unsigned char *src, unsigned char **dest,
-		      int use_graycode)
-{
-  unsigned bpl = (x + 7) / 8;           /* bytes per line in dest plane */
-  unsigned i, k = 8;
-  int p;
-  unsigned long line;
-  extern void *memset(void *s, int c, size_t n);
-  unsigned prev;     /* previous *src byte shifted by 8 bit to the left */
-  register int bits, msb = has_planes - 1;
-  int bitno;
-
-  /* sanity checks */
-  if (encode_planes > has_planes)
-    encode_planes = has_planes;
-  use_graycode = use_graycode != 0 && encode_planes > 1;
-  
-  for (p = 0; p < encode_planes; p++)
-    memset(dest[p], 0, bpl * y);
-  
-  for (line = 0; line < y; line++) {                 /* lines loop */
-    for (i = 0; i * 8 < x; i++) {                    /* dest bytes loop */
-      for (k = 0; k < 8 && i * 8 + k < x; k++) {     /* pixel loop */
-	prev = 0;
-	for (p = 0; p < encode_planes; p++) {        /* bit planes loop */
-	  /* calculate which bit in *src do we want */
-	  bitno = (msb - p) & 7;
-	  /* put this bit with its left neighbor right adjusted into bits */
-	  bits = (prev | *src) >> bitno;
-	  /* go to next *src byte, but keep old */
-	  if (bitno == 0)
-	    prev = *src++;
-	  /* make space for inserting new bit */
-	  dest[p][bpl * line + i] <<= 1;
-	  /* insert bit, if requested apply Gray encoding */
-	  dest[p][bpl * line + i] |= (bits ^ (use_graycode & (bits>>1))) & 1;
-	  /*
-	   * Theorem: Let b(n),...,b(1),b(0) be the digits of a
-	   * binary word and let g(n),...,g(1),g(0) be the digits of the
-	   * corresponding Gray code word, then g(i) = b(i) xor b(i+1).
-	   */
-	}
-	/* skip unused *src bytes */
-	for (;p < has_planes; p++)
-	  if (((has_planes - 1 - p) & 7) == 0)
-	    src++;
-      }
-    }
-    for (p = 0; p < encode_planes; p++)              /* right padding loop */
-      dest[p][bpl * (line + 1) - 1] <<= 8 - k;
-  }
-  
-  return;
-}
-
-/* 
- * Merge the separate bit planes decoded by the JBIG decoder into an
- * integer pixel field. This is essentially the counterpart to
- * jbg_split_planes(). */
-void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode,
-			  void (*data_out)(unsigned char *start, size_t len,
-					   void *file), void *file)
-{
-#define BUFLEN 4096
-  int bpp, bpl;
-  unsigned long line;
-  unsigned i, k = 8;
-  int p, q;
-  unsigned char buf[BUFLEN];
-  unsigned char *bp = buf;
-  unsigned char **src;
-  unsigned long x, y;
-  unsigned v;
-
-  /* sanity check */
-  use_graycode = use_graycode != 0;
-  
-  x = jbg_dec_getwidth(s);
-  y = jbg_dec_getheight(s);
-  if (x <= 0 || y <= 0)
-    return;
-  bpp = (s->planes + 7) / 8;   /* bytes per pixel in dest image */
-  bpl = (x + 7) / 8;           /* bytes per line in src plane */
-
-  if (index[s->order & 7][LAYER] == 0)
-    if (s->ii[0] < 1)
-      return;
-    else
-      src = s->lhp[(s->ii[0] - 1) & 1];
-  else
-    src = s->lhp[s->d & 1];
-  
-  for (line = 0; line < y; line++) {                    /* lines loop */
-    for (i = 0; i * 8 < x; i++) {                       /* src bytes loop */
-      for (k = 0; k < 8 && i * 8 + k < x; k++) {        /* pixel loop */
-	for (p = (s->planes-1) & ~7; p >= 0; p -= 8) {  /* dest bytes loop */
-	  v = 0;
-	  for (q = 0; q < 8 && p+q < s->planes; q++)    /* pixel bit loop */
-	    v = (v << 1) |
-	      (((src[p+q][bpl * line + i] >> (7 - k)) & 1) ^
-	       (use_graycode & v));
-	  *bp++ = v;
-	  if (bp - buf == BUFLEN) {
-	    data_out(buf, BUFLEN, file);
-	    bp = buf;
-	  }
-	}
-      }
-    }
-  }
-  
-  if (bp - buf > 0)
-    data_out(buf, bp - buf, file);
-  
-  return;
-}
diff --git a/converter/other/jbig/jbig.doc b/converter/other/jbig/jbig.doc
deleted file mode 100644
index 10eeda80..00000000
--- a/converter/other/jbig/jbig.doc
+++ /dev/null
@@ -1,721 +0,0 @@
-
-Using the JBIG-KIT library
---------------------------
-
-Markus Kuhn -- 1998-04-10
-
-
-This text explains how to include the functions provided by the
-JBIG-KIT portable image compression library into your application
-software.
-
-
-1  Introduction to JBIG
-
-Below follows a short introduction into some technical aspects of the
-JBIG standard. More detailed information is provided in the
-"Introduction and overview" section of the JBIG standard. Information
-about how to obtain a copy of the standard is available on the
-Internet from <http://www.itu.ch/> or <http://www.iso.ch/>.
-
-Image data encoded with the JBIG algorithm is separated into planes,
-layers, and stripes. Each plane contains one bit per pixel. The number
-of planes stored in a JBIG data stream is the number of bits per
-pixel. Resolution layers are numbered from 0 to D with 0 being the
-layer with the lowest resolution and D the layer with the highest one.
-Each next higher resolution layer has exactly twice the number of rows
-and columns than the previous one. Layer 0 is encoded independently of
-any other data, all other resolution layers are encoded as only the
-difference between the next lower and the current layer. For
-applications that require very quick access to parts of an image it is
-possible to divide an image into several horizontal stripes. All
-stripes of one resolution layer have equal size except perhaps the
-final one. The number of stripes of an image is equal in all
-resolution layers and in all bit planes.
-
-The compressed data stream specified by the JBIG standard is called a
-bi-level image entity (BIE). A BIE consists of a 20-byte header,
-followed by an optional 1728-byte table (usually not present, except
-in special applications) followed by a sequence of stripe data
-entities (SDE). SDEs are the data blocks of which each encodes the
-content of one single stripe in one plane and resolution layer.
-Between the SDEs, other information blocks (called floating marker
-segments) can also be present, which change certain parameters of the
-algorithm in the middle of an image or contain additional application
-specific information. A BIE looks like this:
-
-
-          +------------------------------------------------+
-          |                                                |
-          |  20-byte header (with image size, #planes,     |
-          |  #layers, stripe size, first layer, options,   |
-          |  SDE ordering, ...)                            |
-          |                                                |
-          +------------------------------------------------+
-          |                                                |
-          |           optional 1728-byte table             |
-          |                                                |
-          +------------------------------------------------+
-          |                                                |
-          |              stripe data entity                |
-          |                                                |
-          +------------------------------------------------+
-          |                                                |
-          |       optional floating marker segments        |
-          |                                                |
-          +------------------------------------------------+
-          |                                                |
-          |              stripe data entity                |
-          |                                                |
-          +------------------------------------------------+
-            ...
-          +------------------------------------------------+
-          |                                                |
-          |              stripe data entity                |
-          |                                                |
-          +------------------------------------------------+
-
-
-One BIE can contain all resolution layers of an image, but it is also
-possible to store various resolution layers in several BIEs. The BIE
-header contains the number of the first and the last resolution layer
-stored in this BIE, as well as the size of the highest resolution
-layer stored in this BIE. Progressive coding is deactivated by simply
-storing the image in one single resolution layer.
-
-Different applications might have different requirements for the order
-in which the SDEs for stripes of various planes and layers are stored
-in the BIE, so all possible sensible orderings are allowed and
-indicated by four bits in the header.
-
-It is possible to use the raw BIE data stream as specified by the JBIG
-standard directly as the format of a file used for storing images.
-This is what the JBIG<->PBM conversion tools that are provided in this
-package as demonstration applications do. However as the BIE format
-has been designed for a large number of very different applications
-and also in order to allow efficient direct processing by special JBIG
-hardware chip implementations, the BIE header contains only the
-minimum amount of information absolutely required by the decompression
-algorithm. A large number of features expected from a good file format
-are missing in the BIE data stream:
-
-  - no "magic code" in the first few bytes to allow identification
-    of the file on a typeless file system as JBIG encoded and to allow
-    automatic distinction from other compression algorithms
-
-  - no standardized way to encode additional information like a textual
-    description, information about the meaning of various bit planes,
-    the physical size and resolution of the document, etc.
-
-  - a checksum that ensures image integrity
-
-  - encryption and signature mechanisms
-
-  - many things more
-
-Raw BIE data streams alone are consequently no suitable format for
-document archiving and exchange. A standard format for this purpose
-would typically combine a BIE representing the image data together
-with an additional header providing auxiliary information into one
-file. Existing established multi-purpose file formats with a rich set
-of auxiliary information attributes like TIFF could be extended easily
-so that they can also contain JBIG compressed data.
-
-On the other hand, in database applications for instance, a BIE might
-be directly stored in a variable length field. Auxiliary information
-on which efficient search operations are required would then be stored
-in other fields of the same record.
-
-
-2  Compressing an image
-
-2.1  Format of the source image
-
-For processing by the library, the image has to be present in memory
-as separate bitmap planes. Each byte of a bitmap contains eight
-pixels, the most significant bit represents the leftmost of these
-pixels. Each line of a bitmap has to be stored in an integral number
-of bytes. If the image width is not an integral multiple of eight,
-then the final byte has to be padded with zero bits.
-
-For example the 23x5 pixels large single plane image:
-
-   .XXXXX..XXX...X...XXX..
-   .....X..X..X..X..X.....
-   .....X..XXX...X..X.XXX.
-   .X...X..X..X..X..X...X.
-   ..XXX...XXX...X...XXX..
-
-is represented by the 15 bytes
-
-   01111100 11100010 00111000
-   00000100 10010010 01000000
-   00000100 11100010 01011100
-   01000100 10010010 01000100
-   00111000 11100010 00111000
-
-or in hexadecimal notation
-
-   7c e2 38 04 92 40 04 e2 5c 44 92 44 38 e2 38
-
-This is the format used in binary PBM files and it can also be be
-handled directly by the Xlib library of the X Window System.
-
-As JBIG can also handle images with several bit planes, the JBIG-KIT
-library functions accept and return always arrays of pointers to
-bitmaps with one pointer per plane.
-
-For single plane images, the standard recommends that a 0 pixel
-represents the background and a 1 pixel represents the foreground
-color of an image, i.e. 0 is white and 1 is black for scanned paper
-documents. For images with several bits per pixel, the JBIG standard
-makes no recommendations about how various colors should be encoded.
-
-For greyscale images, by using a Gray code instead of a simple binary
-weighted representation of the pixel intensity, some increase in
-coding efficiency can be reached.
-
-A Gray code is also a binary representation of integer numbers, but
-has the property that the representations of the integer numbers i and
-(i+1) differ always in exactly one single bit. For example, the
-numbers 0 to 7 can be represented in normal binary code and Gray code
-as in the following table:
-
-                           normal
-              number    binary code     Gray code
-            ---------------------------------------
-                0           000            000
-                1           001            001
-                2           010            011
-                3           011            010
-                4           100            110
-                5           101            111
-                6           110            101
-                7           111            100
-
-The form of Gray code shown above has the property that the second
-half of the code (numbers 4 - 7) is simply the mirrored first half
-(numbers 3 - 0) with the first bit set to one. This way, arbitrarily
-large Gray codes can be generated quickly by mirroring the above
-example and prefixing the first half with zeros and the second half
-with ones as often as required. In greyscale images, it is common
-practise to use the all-0 code for black and the all-1 code for white.
-
-No matter whether a Gray code or a binary code is used for encoding a
-pixel intensity in several bit planes, it always makes sense to store
-the most significant (leftmost) bit in plane 0, which is transmitted
-first. This way, a decoder could increase the precision of the
-displayed pixel intensities while data is still being received and the
-basic structure of the image will become visible as early as possible
-during the transmission.
-
-
-2.2  A simple compression application
-
-In order to use JBIG-KIT in your application, just link libjbig.a to
-your executable (on Unix systems just add -ljbig and -L. to the
-command line options of your compiler, on other systems you will have
-to write a new Makefile anyway), copy the file jbig.h into your source
-directory and put the line
-
-  #include "jbig.h"
-
-into your source code.
-
-The library interface follows the concepts of object-oriented
-programming. You have to declare a variable (object)
-
-  struct jbg_enc_state se;
-
-which contains the current status of an encoder. Then you initialize
-the encoder by calling the constructor function
-
-  void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y,
-                    int pl, unsigned char **p,
-                    void (*data_out)(unsigned char *start, size_t len,
-                                     void *file),
-                    void *file);
-
-The parameters have the following meaning:
-
-  s             A pointer to the jbg_enc_state structure which you want
-                to initialize.
-
-  x             The width of your image.
-
-  y             The height of your image.
-
-  pl            the number of bitmap planes you want to encode.
-
-  p             A pointer to an array of pl pointers, where each is again
-                pointing to the first byte of a bitmap as described in
-                section 2.1.
-
-  data_out      This is a call-back function which will be called during
-                the compression process by libjbig in order to deliver
-                the BIE data to the application. The parameters of the
-                function data_out are a pointer start to the new block of
-                data to be delivered as well as the number len of delivered
-                bytes. The pointer file is transparently delivered to
-                data_out as specified in jbg_enc_init(). Usually, data_out
-                will write the BIE portion to a file, send it to a
-                network connection or append it to some memory buffer.
-
-  file          A pointer parameter which is transparently passed to
-                data_out() and allows data_out() to distinguish by which
-                compression task it has been called in multi-threaded
-                applications.
-
-In the simplest case, the compression is then started by calling the
-function
-
-  void jbg_enc_out(struct jbg_enc_state *s);
-
-which will deliver the complete BIE to data_out(). After this, a call
-to the destructor function
-
-  void jbg_enc_free(struct jbg_enc_state *s);
-
-will release any memory allocated by the previous functions.
-
-
-A minimal example application which sends the BIE of the above example
-bitmap to stdout looks like this:
-
----------------------------------------------------------------------------
-/* A sample JBIG encoding application */
-
-#include <stdio.h>
-#include "jbig.h"
-
-void output_bie(unsigned char *start, size_t len, void *file)
-{
-  fwrite(start, 1, len, (FILE *) file);
-  
-  return;
-}
-
-int main()
-{
-  unsigned char bitmap[15] = {
-    /* 23 x 5 pixels, "JBIG" */
-    0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2,
-    0x5c, 0x44, 0x92, 0x44, 0x38, 0xe2, 0x38
-  };
-  unsigned char *bitmaps[1] = { bitmap };
-  struct jbg_enc_state se;
-  
-  jbg_enc_init(&se, 23, 5, 1, bitmaps, 
-	       output_bie, stdout);              /* initialize encoder */
-  jbg_enc_out(&se);                                    /* encode image */
-  jbg_enc_free(&se);                    /* release allocated resources */
-  
-  return 0;
-}
----------------------------------------------------------------------------
-
-This software produces a 42 byte long BIE. (JBIG is not very good at
-compressing extremely small images like in this example, because the
-arithmetic encoder requires some startup data in order to generate
-reasonable statistics which influence the compression process and
-because there is some header overhead.)
-
-
-2.3  More about compression
-
-If jbg_enc_out() is called directly after jbg_enc_init(), the
-following default values are used for various compression parameters:
-
-  - Only one single resolution layer is used, i.e. no progressive
-    mode.
-
-  - The number of lines per stripe is selected so that approximately
-    35 stripes per image are used (as recommended in annex C of the
-    standard together with the suggested adaptive template change
-    algorithm). However not less than 2 and not more than 128 lines
-    are used in order to stay within the suggested minimum parameter
-    support range specified in annex A of the standard).
-
-  - All optional parts of the JBIG algorithm are activated (TPBON,
-    TPDON and DPON).
-
-  - The default resolution reduction table and the default deterministic
-    prediction tables are used
-
-  - The maximal vertical offset of the adaptive template pixel is 0
-    and the maximal horizontal offset is 8 (mx = 8, my = 0).
-
-In order to change any of these default parameters, additional
-functions have to be called between jbg_enc_init() and jbg_enc_out().
-
-In order to activate progressive encoding, it is possible to specify
-with 
-
-  void jbg_enc_layers(struct jbg_enc_state *s, int d);
-
-the number d of differential resolution layers which shall be encoded
-in addition to the lowest resolution layer 0. For example, if a 300
-dpi document has to be stored and the lowest resolution layer shall
-have 75 dpi so that a screen previewer can directly decompress only
-the required resolution, then a call
-
-  jbg_enc_layers(&se, 2);
-
-will cause three resolution layers with 75, 150 and 300 dots per inch.
-
-If the application does not know what typical resolutions are used and
-simply wants to ensure that the lowest resolution layer will fit into
-a given maximal window size, then as an alternative, a call to
-
-  int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth,
-                     unsigned long mheight);
-
-will cause the library to automatically determine the suitable number
-of resolutions so that the lowest resolution layer 0 will not be
-larger than mwidth x mheight pixels. E.g. if one wants to ensure that
-systems with a 640 x 480 pixel large screen can decode the required
-resolution directly, then call
-
-  jbg_enc_lrlmax(&se, 640, 480);
-
-The return value is the number of differential layers selected.
-
-After the number of resolution layers has been specified by calls to
-jbg_enc_layers() or jbg_enc_lrlmax(), by default all these layers will
-be written into the BIE. This can be changed with a call to
-
-  int  jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh);
-
-Parameter dl specifies the lowest resolution layer and dh the highest
-resolution layer that will appear in the BIE. If e.g. only layer 0
-shall be written to the first BIE and layer 1 and 2 shall be written
-to a second one, then before writing the first BIE, one calls
-
-  jbg_enc_lrange(&se, 0, 0);
-
-and before writing the second BIE with jbg_enc_out(), one calls
-
-  jbg_enc_lrange(&se, 1, 2);
-
-If any of the parameters is negative, it will be ignored. The return
-value is the total number of differential layers which will represent
-the input image. This way, jbg_enc_lrange(&se, -1, -1) can be used to
-query the layer of the full image.
-
-A number of other more exotic options of the JBIG algorithm can be
-modified by calling
-
-  void jbg_enc_options(struct jbg_enc_state *s, int order, int options,
-                       long l0, int mx, int my);
-
-before calling jbg_enc_out().
-
-The order parameter can be a combination of the bits JBG_HITOLO,
-JBG_SEQ, JBG_ILEAVE and JBG_SMID and it determines in which order
-the SDEs are stored in the BIE. The bits have the following meaning:
-
-  JBG_HITOLO   Usually, the lower resolution layers are stored before
-               the higher resolution layers, so that a decoder can
-               already start to display a low resolution version of
-               the full image once a prefix of the BIE has been
-               received. When this bit is set however, the BIE will
-               contain the higher layers before the lower layers. This
-               avoids additional buffer memory in the encoder and is
-               intended for applications where the encoder is connected
-               to a database which can easily reorder the SDEs before
-               sending them to a decoder. Warning: JBIG decoders are
-               not expected to support the HITOLO option (e.g. the
-               JBIG-KIT decoder does currently not) so you should
-               normally not use it.
-
-  JBG_SEQ      Usually, at first all stripes of one resolution layer
-               are written to the BIE and then all stripes of the next
-               layer, and so on. When the SEQ bit is set however, then
-               all layers of the first stripe will be written,
-               followed by all layers of the second stripe, etc. This
-               option also should normally never be required and is
-               not supported by the current JBIG-KIT decoder.
-
-  JBG_SMID     In case there exist several bit planes, then the order of
-               the stripes is determined by 3 loops over all stripes,
-               all planes and all layers. When SMID is set, the loop
-               over all stripes is the middle loop.
-
-  JBG_ILEAVE   If this bit is set, then at first all layers of one
-               plane are written before the encoder starts with the next
-               plane.
-
-The above description might be somewhat confusing, but the following
-table (see also Table 11 in ITU-T T.82) makes clear how the three bits
-JBG_SEQ, JBIG_ILEAVE and JBG_SMID influence the ordering of the loops
-over all stripes, planes and layers:
-
-
-                                                 Loops:
-    JBG_SEQ   JBG_ILEAVE   JBG_SMID   |  Outer   Middle    Inner
-  ------------------------------------+---------------------------
-       0           0           0      |    p        d        s
-       0           1           0      |    d        p        s
-       0           1           1      |    d        s        p
-       1           0           0      |    s        p        d
-       1           0           1      |    p        s        d
-       1           1           0      |    s        d        p
-
-                                       p: plane, s: stripe, d: layer
-
-
-By default, the order combination JBG_ILEAVE | JBG_SMID is used.
-
-The options value can contain the following bits, which activate
-some of the optional algorithms defined by JBIG:
-
-  JBG_LRLTWO     Normally, in the lowest resolution layer, pixels
-                 from three lines around the next pixel are used
-                 in order to determine the context in which the next
-                 pixel is encoded. Some people in the JBIG committee
-                 seem to have argued that using only 2 lines will
-                 make software implementations a little bit faster,
-                 however others have argued that using only two lines
-                 will decrease compression efficiency by around 5%.
-                 As you might expect from a committee, now both
-                 alternatives are allowed and if JBG_LRLTWO is set,
-                 the slightly faster but 5% less well compressing two
-                 line alternative is selected. God bless the committees.
-                 Although probably nobody will ever need this option,
-                 it has been implemented in JBIG-KIT and is off by
-                 default.
-
-  JBG_TPDON      This activates the "typical prediction" algorithm
-                 for differential layers which avoids that large
-                 areas of equal color have to be encoded at all.
-                 This is on by default and there is no good reason to
-                 switch it off except for debugging or preparing data
-                 for cheap JBIG hardware which does not support this
-                 option.
-
-  JBG_TPBON      Like JBG_TPDON this activates the "typical prediction"
-                 algorithm in the lowest resolution layer. Also activated
-                 by default.
-
-  JBG_DPON       This bit activates for the differential resolution
-                 layers the "deterministic prediction" algorithm,
-                 which avoids that higher resolution layer pixels are
-                 encoded when their value can already be determined
-                 with the knowledge of the neighbor pixels, the
-                 corresponding lower resolution pixels and the
-                 resolution reduction algorithm. This is also
-                 activated by default and one only might perhaps want
-                 to deactivate it if the default resolution reduction
-                 algorithm is replaced by a new one.
-
-  JBG_DELAY_AT   Use a slightly less efficient algorithm to determine
-                 when an adaptive template change is necessary. With
-                 this bit set, the encoder output is compatible to the
-                 conformance test examples in cause 7.2 of ITU-T T.82.
-                 Then all adaptive template changes are delayed until
-                 the first line of the next stripe. This option is by
-                 default deactivated and only required for passing a
-                 special compatibility test suite.
-
-In addition, parameter l0 in jbg_enc_options() allows you to specify
-the number of lines per stripe in resolution layer 0. The parameters
-mx and my change the maximal offset allowed for the adaptive template
-pixel. The JBIG-KIT implementation allows currently a maximal mx value
-of 23 in the encoder and 32 in the decoder. Parameter my is at the
-moment ignored and always set to 0. As the standard requires of all
-decoder implementations only a maximum supported mx = 16 and my = 0,
-higher values should normally be avoided in order to guarantee
-interoperability. Default is mx = 8 and my = 0. If any of the
-parameters order, options, l0, mx or my is negative, then this value
-is ignored and the current value stays unmodified.
-
-The resolution reduction and deterministic prediction tables can also
-be replaced. However as these options are anyway only for experts,
-please have a look at the source code of jbg_enc_out() and the struct
-members dppriv and res_tab of struct jbg_enc_state for the details of
-how to do this in case you really need it. The functions
-jbg_int2dppriv and jbg_dppriv2int are provided in order to convert the
-DPTABLE data from the format used in the standard into the more
-efficient format used internally by JBIG-KIT.
-
-If you want to encode a greyscale image, you can use the library
-function
-
-  void jbg_split_planes(unsigned long x, unsigned long y, int has_planes,
-                        int encode_planes,
-                        const unsigned char *src, unsigned char **dest,
-                        int use_graycode);
-
-It separates an image in which each pixel is represented by one or
-more bytes into separate bitplanes. The dest array of pointers to
-these bitplanes can then be handed over to jbg_enc_init(). The
-variables x and y specify the width and height of the image in pixels,
-and has_planes specifies how many bits per pixel are used. As each
-pixel is represented by an integral number of consecutive bytes, of
-which each contains up to eight bits, the total length of the input
-image array src[] will therefore be x * y * ((has_planes + 7) / 8)
-bytes. The pixels are stored as usually in English reading order, and
-for each pixel the integer value is stored with the most significant
-byte coming first (Bigendian). This is exactly the format used in raw
-PGM files. In encode_planes, the number of bitplanes that shall be
-extracted can be specified. This allows for instance to extract only
-the most significant 8 bits of a 12-bit image, where each pixel is
-represented by two bytes, by specifying has_planes = 12 and
-encode_planes = 8. If use_graycode is zero, then the binary code of
-the pixel integer values will be used instead of the Gray code. Plane
-0 contains always the most significant bit.
-
-
-3  Decompressing an image
-
-Like with the compression functions, if you want to use the JBIG-KIT
-library, you have to put the line
-
-  #include "jbig.h"
-
-into your source code and link your executable with libjbig.a.
-
-The state of a JBIG decoder is stored completely in a struct and you
-will have to define a variable like
-
-  struct jbg_dec_state sd;
-
-which is initialized by a call to
-
-  void jbg_dec_init(struct jbg_dec_state *s);
-
-After this, you can directly start to pass data from the BIE to the decoder
-by calling the function
-
-  int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len,
-                 size_t *cnt);
-
-The pointer data points to the first byte of a data block with length
-len, which contains bytes from a BIE. It is not necessary to pass a
-whole BIE at once to jbg_dec_in(), it can arrive fragmented in any way
-by calling jbg_dec_in() several times. It is also possible to send
-several BIEs concatenated to jbg_dec_in(), however these then have to
-fit together. If you send several BIEs to the decoder, the lowest
-resolution layer in each following BIE has to be the highest
-resolution layer in the previous BIE plus one and the image sizes and
-number of planes also have to fit together, otherwise jbg_dec_in()
-will return the error JBG_ENOCONT after the header of the new BIE has
-been received completely.
-
-If pointer cnt is not NULL, then the number of bytes actually read
-from the data block is stored there. In case the data block did not
-contain the end of the BIE, then the value JBG_EAGAIN will be returned
-and *cnt equals len.
-
-Once the end of a BIE has been reached, the return value of
-jbg_dec_in() will be JBG_EOK. After this has happened, the functions
-and macros
-
-  long jbg_dec_getwidth(struct jbg_dec_state *s);
-  long jbg_dec_getheight(struct jbg_dec_state *s);
-  int jbg_dec_getplanes(struct jbg_dec_state *s);
-  unsigned char *jbg_dec_getimage(struct jbg_dec_state *s, int plane);
-  long jbg_dec_getsize(struct jbg_dec_state *s);
-
-can be used to query the dimensions of the now completely decoded
-image and to get a pointer to all bitmap planes. The bitmaps are
-stored as described in section 2.1. The function jbg_dec_getsize()
-calculates the number of bytes which one bitmap requires.
-
-The function
-
-  void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode,
-                            void (*data_out)(unsigned char *start, size_t len,
-                                             void *file), void *file);
-
-allows you to merge the bitplanes that can be accessed individually
-with jbg_dec_getimage() into an array with one or more bytes per pixel
-(i.e., the format provided to jbg_split_planes()). If use_graycode is
-zero, then a binary encoding will be used. The output array will be
-delivered via the callback function data_out, exactly in the same way
-in which the encoder provides the BIE. The function
-
-  long jbg_dec_getsize_merged(const struct jbg_dec_state *s);
-
-determines how long the data array delivered by jbg_dec_merge_planes()
-is going to be.
-
-Before calling jbg_dec_in() the first time, it is possible to specify with
-a call to
-
-  void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax,
-                       unsigned long ymax);
-
-an abort criterion for progressively encoded images. For instance if an
-application will display a whole document on a screen which is 1024 x
-768 pixels large, then this application should call
-
-  jbg_dec_maxsize(&sd, 1024, 768);
-
-before the decoding process starts. If the image has been encoded in
-progressive mode (i.e. with several resolution layers), then the
-decoder will stop with a return value JBG_EOK_INTR after the largest
-resolution layer that is still smaller than 1024 x 768. However this
-is no guarantee that the image which can then be read out using
-jbg_dec_getimage(), etc. is really not larger than the specified
-maximal size. The application will have to check the size of the
-image, because the decoder does not automatically apply a resolution
-reduction if no suitable resolution layer is available in the BIE.
-
-If jbg_dec_in() returned JBG_EOK_INTR or JBG_EOK, then it is possible
-to continue calling jbg_dec_in() with the remaining data in order to
-either decode the remaining resolution layers of the current BIE or in
-order to add another BIE with additional resolution layers. In both
-cases, after jbg_dec_in() returned JBG_EOK_INTR or JBG_EOK, *cnt is
-probably not equal to len and the remainder of the data block which
-has not yet been processed by the decoder has to be delivered to
-jbg_dec_in() again.
-
-If any other return value than JBG_EOK, JBG_EOK_INTR or JBG_EAGAIN
-has been returned by jbg_dec_in(), then an error has occurred and
-
-  void jbg_dec_free(struct jbg_dec_state *s);
-
-should be called in order to release any allocated memory. The
-destructor jbg_dec_free() should of course also be called, once the
-decoded bitmap returned by jbg_dec_getimage() is no longer required
-and the memory can be released.
-
-The function
-
-  const char *jbg_strerror(int errnum, int language);
-
-returns a pointer to a short single line test message which explains
-the return value of jbg_dec_in(). This message can be used in order to
-provide the user a brief informative message about what when wrong
-while decompressing the JBIG image. The error messages are available
-in several languages and in several character sets. Currently
-supported are the following values for the language parameter:
-
-  JBG_EN              English messages in ASCII
-  JBG_DE_8859_1       German messages in ISO 8859-1 Latin 1 character set
-  JBG_DE_UTF_8        German messages in ISO 10646/Unicode UTF-8 encoding
-
-
-The current implementation of the JBIG-KIT decoder has the following
-limitations:
-
-  - The maximal horizontal offset mx of the adaptive template pixel
-    must not be larger than 32 and the maximal vertical offset must
-    be zero.
-
-  - HITOLO and SEQ bits must not be set in the order value.
-
-A more detailed description of the JBIG-KIT implementation is
-
-  Markus Kuhn: Effiziente Kompression von bi-level Bilddaten durch
-  kontextsensitive arithmetische Codierung. Studienarbeit, Lehrstuhl
-  für Betriebssysteme, IMMD IV, Universität Erlangen-Nürnberg,
-  Erlangen, July 1995. (German, 62 pages)
-  <http://www.cl.cam.ac.uk/~mgk25/kuhn-sta.pdf>
-
-Please quote the above if you use JBIG-KIT in your research project.
-
-*** Happy compressing ***
-
-[end]
diff --git a/converter/other/jbig/jbig.h b/converter/other/jbig/jbig.h
deleted file mode 100644
index dd9a76f3..00000000
--- a/converter/other/jbig/jbig.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- *  Header file for the portable free JBIG compression library
- *
- *  Markus Kuhn -- mkuhn@acm.org
- *
- *  $Id: jbig.h,v 1.9 1999-11-16 15:58:45+00 mgk25 Rel $
- */
-
-#ifndef JBG_H
-#define JBG_H
-
-#include <stddef.h>
-
-/*
- * JBIG-KIT version number
- */
-
-#define JBG_VERSION    "1.1"
-
-/*
- * Buffer block for SDEs which are temporarily stored by encoder
- */
-
-#define JBG_BUFSIZE 4000
-
-struct jbg_buf {
-  unsigned char d[JBG_BUFSIZE];              /* one block of a buffer list */
-  int len;                             /* length of the data in this block */
-  struct jbg_buf *next;                           /* pointer to next block */
-  struct jbg_buf *previous;                   /* pointer to previous block *
-					       * (unused in freelist)      */
-  struct jbg_buf *last;     /* only used in list head: final block of list */
-  struct jbg_buf **free_list;   /* pointer to pointer to head of free list */
-};
-
-/*
- * Maximum number of allowed ATMOVEs per stripe
- */
-
-#define JBG_ATMOVES_MAX  64
-
-/*
- * Option and order flags
- */
-
-#define JBG_HITOLO     0x08
-#define JBG_SEQ        0x04
-#define JBG_ILEAVE     0x02
-#define JBG_SMID       0x01
-
-#define JBG_LRLTWO     0x40
-#define JBG_VLENGTH    0x20
-#define JBG_TPDON      0x10
-#define JBG_TPBON      0x08
-#define JBG_DPON       0x04
-#define JBG_DPPRIV     0x02
-#define JBG_DPLAST     0x01
-
-#define JBG_DELAY_AT   0x100  /* delay ATMOVE until the first line of the next
-			       * stripe. Option available for compatibility
-			       * with conformance test example in clause 7.2.*/
-
-
-/*
- * Possible error code return values
- */
-
-#define JBG_EOK        0
-#define JBG_EOK_INTR   1
-#define JBG_EAGAIN     2
-#define JBG_ENOMEM     3
-#define JBG_EABORT     4
-#define JBG_EMARKER    5
-#define JBG_ENOCONT    6
-#define JBG_EINVAL     7
-#define JBG_EIMPL      8
-
-/*
- * Language code for error message strings (based on ISO 639 2-letter
- * standard language name abbreviations).
- */ 
-
-#define JBG_EN         0        /* English */
-#define JBG_DE_8859_1  1        /* German in ISO Latin 1 character set */
-#define JBG_DE_UTF_8   2        /* German in Unicode UTF-8 encoding */
-
-/*
- * Status description of an arithmetic encoder
- */
-
-struct jbg_arenc_state {
-  unsigned char st[4096];    /* probability status for contexts, MSB = MPS */
-  unsigned long c;                /* C register, base of coding intervall, *
-                                   * layout as in Table 23                 */
-  unsigned long a;      /* A register, normalized size of coding intervall */
-  long sc;        /* counter for buffered 0xff values which might overflow */
-  int ct;  /* bit shift counter, determines when next byte will be written */
-  int buffer;                /* buffer for most recent output byte != 0xff */
-  void (*byte_out)(int, void *); /* function which receives all PSCD bytes */
-  void *file;                              /* parameter passed to byte_out */
-};
-
-
-/*
- * Status description of an arithmetic decoder
- */
-
-struct jbg_ardec_state {
-  unsigned char st[4096];    /* probability status for contexts, MSB = MPS */
-  unsigned long c;                /* C register, base of coding intervall, *
-                                   * layout as in Table 25                 */
-  unsigned long a;      /* A register, normalized size of coding intervall */
-  int ct;     /* bit shift counter, determines when next byte will be read */
-  unsigned char *pscd_ptr;               /* pointer to next PSCD data byte */
-  unsigned char *pscd_end;                   /* pointer to byte after PSCD */
-  enum {
-    JBG_OK,                        /* symbol has been successfully decoded */
-    JBG_READY,             /* no more bytes of this PSCD required, marker  *
-		            * encountered, probably more symbols available */
-    JBG_MORE,          /* more PSCD data bytes required to decode a symbol */
-    JBG_MARKER   /* more PSCD data bytes required, ignored final 0xff byte */
-  } result;                              /* result of previous decode call */
-  int startup;                            /* controls initial fill of s->c */
-};
-
-#ifdef TEST_CODEC
-void arith_encode_init(struct jbg_arenc_state *s, int reuse_st);
-void arith_encode_flush(struct jbg_arenc_state *s);
-void arith_encode(struct jbg_arenc_state *s, int cx, int pix);
-void arith_decode_init(struct jbg_ardec_state *s, int reuse_st);
-int arith_decode(struct jbg_ardec_state *s, int cx);
-#endif
-
- 
-/*
- * Status of a JBIG encoder
- */
-
-struct jbg_enc_state {
-  int d;                            /* resolution layer of the input image */
-  unsigned long xd, yd;    /* size of the input image (resolution layer d) */
-  int planes;                         /* number of different bitmap planes */
-  int dl;                       /* lowest resolution layer in the next BIE */
-  int dh;                      /* highest resolution layer in the next BIE */
-  unsigned long l0;                /* number of lines per stripe at lowest *
-                                    * resolution layer 0                   */
-  unsigned long stripes;    /* number of stripes required  (determ. by l0) */
-  unsigned char **lhp[2];    /* pointers to lower/higher resolution images */
-  int *highres;                 /* index [plane] of highres image in lhp[] */
-  int order;                                    /* SDE ordering parameters */
-  int options;                                      /* encoding parameters */
-  unsigned mx, my;                           /* maximum ATMOVE window size */
-  int *tx;       /* array [plane] with x-offset of adaptive template pixel */
-  char *dppriv;         /* optional private deterministic prediction table */
-  char *res_tab;           /* table for the resolution reduction algorithm */
-  struct jbg_buf ****sde;      /* array [stripe][layer][plane] pointers to *
-				* buffers for stored SDEs                  */
-  struct jbg_arenc_state *s;  /* array [planes] for arithm. encoder status */
-  struct jbg_buf *free_list; /* list of currently unused SDE block buffers */
-  void (*data_out)(unsigned char *start, size_t len, void *file);
-                                                    /* data write callback */
-  void *file;                            /* parameter passed to data_out() */
-  char *tp;    /* buffer for temp. values used by diff. typical prediction */
-};
-
-
-/*
- * Status of a JBIG decoder
- */
-
-struct jbg_dec_state {
-  /* data from BIH */
-  int d;                             /* resolution layer of the full image */
-  int dl;                            /* first resolution layer in this BIE */
-  unsigned long xd, yd;     /* size of the full image (resolution layer d) */
-  int planes;                         /* number of different bitmap planes */
-  unsigned long l0;                /* number of lines per stripe at lowest *
-				    * resolution layer 0                   */
-  unsigned long stripes;    /* number of stripes required  (determ. by l0) */
-  int order;                                    /* SDE ordering parameters */
-  int options;                                      /* encoding parameters */
-  int mx, my;                                /* maximum ATMOVE window size */
-  char *dppriv;         /* optional private deterministic prediction table */
-
-  /* loop variables */
-  unsigned long ii[3];  /* current stripe, layer, plane (outer loop first) */
-
-  /*
-   * Pointers to array [planes] of lower/higher resolution images.
-   * lhp[d & 1] contains image of layer d. 
-   */
-  unsigned char **lhp[2];
-
-  /* status information */
-  int **tx, **ty;   /* array [plane][layer-dl] with x,y-offset of AT pixel */
-  struct jbg_ardec_state **s;    /* array [plane][layer-dl] for arithmetic *
-				  * decoder status */
-  int **reset;     /* array [plane][layer-dl] remembers if previous stripe *
-		    * in that plane/resolution ended with SDRST.           */
-  unsigned long bie_len;                    /* number of bytes read so far */
-  unsigned char buffer[20]; /* used to store BIH or marker segments fragm. */
-  int buf_len;                                /* number of bytes in buffer */
-  unsigned long comment_skip;      /* remaining bytes of a COMMENT segment */
-  unsigned long x;              /* x position of next pixel in current SDE */
-  unsigned long i; /* line in current SDE (first line of each stripe is 0) */ 
-  int at_moves;                /* number of AT moves in the current stripe */
-  unsigned long at_line[JBG_ATMOVES_MAX];           /* lines at which an   *
-					             * AT move will happen */
-  int at_tx[JBG_ATMOVES_MAX], at_ty[JBG_ATMOVES_MAX]; /* ATMOVE offsets in *
-						       * current stripe    */
-  unsigned long line_h1, line_h2, line_h3;     /* variables of decode_pscd */
-  unsigned long line_l1, line_l2, line_l3;
-  int pseudo;         /* flag for TPBON/TPDON:  next pixel is pseudo pixel */
-  int **lntp;        /* flag [plane][layer-dl] for TP: line is not typical */
-
-  unsigned long xmax, ymax;         /* if possible abort before image gets *
-				     * larger than this size */
-  int dmax;                                      /* abort after this layer */
-};
-
-
-/* some macros (too trivial for a function) */
-
-#define jbg_dec_getplanes(s)     ((s)->planes)
-
-
-/* function prototypes */
-
-void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y,
-		  int planes, unsigned char **p,
-		  void (*data_out)(unsigned char *start, size_t len,
-				   void *file),
-		  void *file);
-int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth,
-		   unsigned long mheight);
-void jbg_enc_layers(struct jbg_enc_state *s, int d);
-int  jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh);
-void jbg_enc_options(struct jbg_enc_state *s, int order, int options,
-		     long l0, int mx, int my);
-void jbg_enc_out(struct jbg_enc_state *s);
-void jbg_enc_free(struct jbg_enc_state *s);
-
-void jbg_dec_init(struct jbg_dec_state *s);
-void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax,
-		     unsigned long ymax);
-int  jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len,
-		size_t *cnt);
-long jbg_dec_getwidth(const struct jbg_dec_state *s);
-long jbg_dec_getheight(const struct jbg_dec_state *s);
-unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane);
-long jbg_dec_getsize(const struct jbg_dec_state *s);
-void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode,
-			  void (*data_out)(unsigned char *start, size_t len,
-					   void *file), void *file);
-long jbg_dec_getsize_merged(const struct jbg_dec_state *s);
-void jbg_dec_free(struct jbg_dec_state *s);
-
-const char *jbg_strerror(int errnum, int language);
-void jbg_int2dppriv(unsigned char *dptable, const char *internal);
-void jbg_dppriv2int(char *internal, const unsigned char *dptable);
-unsigned long jbg_ceil_half(unsigned long x, int n);
-void jbg_split_planes(unsigned long x, unsigned long y, int has_planes,
-		      int encode_planes,
-		      const unsigned char *src, unsigned char **dest,
-		      int use_graycode);
-
-#endif /* JBG_H */
diff --git a/converter/other/jbig/jbig_tab.c b/converter/other/jbig/jbig_tab.c
deleted file mode 100644
index 55183503..00000000
--- a/converter/other/jbig/jbig_tab.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- *  Probability estimation tables for the arithmetic encoder/decoder
- *  given by ITU T.82 Table 24.
- *
- *  $Id: jbig_tab.c,v 1.6 1998-04-05 18:36:19+01 mgk25 Rel $
- */
-
-short jbg_lsz[113] = {
-  0x5a1d, 0x2586, 0x1114, 0x080b, 0x03d8, 0x01da, 0x00e5, 0x006f,
-  0x0036, 0x001a, 0x000d, 0x0006, 0x0003, 0x0001, 0x5a7f, 0x3f25,
-  0x2cf2, 0x207c, 0x17b9, 0x1182, 0x0cef, 0x09a1, 0x072f, 0x055c,
-  0x0406, 0x0303, 0x0240, 0x01b1, 0x0144, 0x00f5, 0x00b7, 0x008a,
-  0x0068, 0x004e, 0x003b, 0x002c, 0x5ae1, 0x484c, 0x3a0d, 0x2ef1,
-  0x261f, 0x1f33, 0x19a8, 0x1518, 0x1177, 0x0e74, 0x0bfb, 0x09f8,
-  0x0861, 0x0706, 0x05cd, 0x04de, 0x040f, 0x0363, 0x02d4, 0x025c,
-  0x01f8, 0x01a4, 0x0160, 0x0125, 0x00f6, 0x00cb, 0x00ab, 0x008f,
-  0x5b12, 0x4d04, 0x412c, 0x37d8, 0x2fe8, 0x293c, 0x2379, 0x1edf,
-  0x1aa9, 0x174e, 0x1424, 0x119c, 0x0f6b, 0x0d51, 0x0bb6, 0x0a40,
-  0x5832, 0x4d1c, 0x438e, 0x3bdd, 0x34ee, 0x2eae, 0x299a, 0x2516,
-  0x5570, 0x4ca9, 0x44d9, 0x3e22, 0x3824, 0x32b4, 0x2e17, 0x56a8,
-  0x4f46, 0x47e5, 0x41cf, 0x3c3d, 0x375e, 0x5231, 0x4c0f, 0x4639,
-  0x415e, 0x5627, 0x50e7, 0x4b85, 0x5597, 0x504f, 0x5a10, 0x5522,
-  0x59eb
-};
-
-unsigned char jbg_nmps[113] = {
-    1,   2,   3,   4,   5,   6,   7,   8,
-    9,  10,  11,  12,  13,  13,  15,  16,
-   17,  18,  19,  20,  21,  22,  23,  24,
-   25,  26,  27,  28,  29,  30,  31,  32,
-   33,  34,  35,   9,  37,  38,  39,  40,
-   41,  42,  43,  44,  45,  46,  47,  48,
-   49,  50,  51,  52,  53,  54,  55,  56,
-   57,  58,  59,  60,  61,  62,  63,  32,
-   65,  66,  67,  68,  69,  70,  71,  72,
-   73,  74,  75,  76,  77,  78,  79,  48,
-   81,  82,  83,  84,  85,  86,  87,  71,
-   89,  90,  91,  92,  93,  94,  86,  96,
-   97,  98,  99, 100,  93, 102, 103, 104,
-   99, 106, 107, 103, 109, 107, 111, 109,
-  111
-};
-
-/*
- * least significant 7 bits (mask 0x7f) of jbg_nlps[] contain NLPS value,
- * most significant bit (mask 0x80) contains SWTCH bit
- */
-unsigned char jbg_nlps[113] = {
-  129,  14,  16,  18,  20,  23,  25,  28,
-   30,  33,  35,   9,  10,  12, 143,  36,
-   38,  39,  40,  42,  43,  45,  46,  48,
-   49,  51,  52,  54,  56,  57,  59,  60,
-   62,  63,  32,  33, 165,  64,  65,  67,
-   68,  69,  70,  72,  73,  74,  75,  77,
-   78,  79,  48,  50,  50,  51,  52,  53,
-   54,  55,  56,  57,  58,  59,  61,  61,
-  193,  80,  81,  82,  83,  84,  86,  87,
-   87,  72,  72,  74,  74,  75,  77,  77,
-  208,  88,  89,  90,  91,  92,  93,  86,
-  216,  95,  96,  97,  99,  99,  93, 223,
-  101, 102, 103, 104,  99, 105, 106, 107,
-  103, 233, 108, 109, 110, 111, 238, 112,
-  240
-};
-
-/*
- * Resolution reduction table given by ITU-T T.82 Table 17
- */
-
-char jbg_resred[4096] = {
-  0,0,0,1,0,0,0,1,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,
-  0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1,1,
-  0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,
-  1,0,0,1,0,0,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0,
-  0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,1,0,0,0,1,0,1,1,0,1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,
-  1,1,1,0,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,
-  1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,
-  0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0,1,1,
-  1,0,0,1,0,0,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,
-  0,0,1,0,1,1,1,1,0,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,
-  0,0,0,0,1,0,0,1,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,
-  0,0,1,0,0,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,
-  0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,0,1,0,1,1,0,0,0,1,0,0,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,0,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,1,
-  0,0,1,0,0,1,1,1,0,0,0,0,1,0,0,1,0,0,0,1,1,1,1,0,1,0,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,1,0,
-  0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,1,
-  0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,1,0,0,1,1,1,0,1,1,0,0,1,1,
-  0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,1,0,0,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,1,0,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,
-  0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
-  0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,
-  0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,1,0,1,1,0,1,1,1,0,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,
-  1,0,1,0,1,0,0,1,1,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,1,1,0,1,1,1,
-  0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,0,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,0,0,1,1,1,1,1,1,1,1,1,
-  1,1,1,0,1,0,0,0,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,
-  1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,
-  0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,0,0,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,1,0,1,0,0,0,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,
-  1,0,0,0,1,0,0,0,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,0,1,1,0,
-  0,0,1,1,1,1,1,1,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
-  0,0,1,0,1,0,1,1,0,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,
-  0,0,1,0,1,0,1,1,0,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,
-  0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
-  0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,
-  0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1,
-  0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,
-  1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,
-  0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,
-  0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,
-  0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,1,1,1,1,
-  0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,
-  0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0,1,1,1
-};
-
-/*
- * Deterministic prediction tables given by ITU-T T.82 tables
- * 19 to 22. The table below is organized differently, the
- * index bits are permutated for higher efficiency.
- */
-
-char jbg_dptable[256 + 512 + 2048 + 4096] = {
-  /* phase 0: offset=0 */
-  0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,2,2,2,2,2,2,2,
-  0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,2,0,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  /* phase 1: offset=256 */
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,0,2,0,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,2,1,2,1,2,2,2,2,1,1,1,1,2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,2,
-  0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,0,2,2,2,2,2,2,2,
-  0,2,0,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,0,0,2,2,2,2,2,0,0,2,2,2,2,2,
-  0,2,2,2,2,1,2,1,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,
-  1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,1,1,2,2,2,2,2,0,2,2,2,2,2,2,
-  2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2,2,2,2,2,2,
-  0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,2,
-  2,2,2,2,2,1,1,1,2,2,2,2,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2,0,2,0,2,2,2,2,2,0,2,0,2,2,2,2,1,
-  0,2,0,2,2,1,2,1,2,2,2,2,1,1,1,1,0,0,0,0,2,2,2,2,0,2,0,2,2,2,2,1,
-  2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,0,2,2,2,2,2,
-  2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,2,2,2,2,1,
-  2,2,2,2,2,2,2,2,0,2,0,2,2,1,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,
-  /* phase 2: offset=768 */
-  2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1,
-  0,2,2,2,2,1,2,1,2,2,2,2,1,2,1,2,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,
-  2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,1,2,1,2,2,2,2,2,1,1,1,
-  2,0,2,2,2,1,2,1,0,2,2,2,1,2,1,2,2,2,2,0,2,2,2,2,0,2,0,2,2,2,2,2,
-  0,2,0,0,1,1,1,1,2,2,2,2,1,1,1,1,0,2,0,2,1,1,1,1,2,2,2,2,1,1,1,1,
-  2,2,0,2,2,2,1,2,2,2,2,2,1,2,1,2,2,2,0,2,2,1,2,1,0,2,0,2,1,1,1,1,
-  2,0,0,2,2,2,2,2,0,2,0,2,2,0,2,0,2,0,2,0,2,2,2,1,2,2,0,2,1,1,2,1,
-  2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1,
-  0,0,0,0,2,2,2,2,0,0,0,0,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,0,2,2,2,2,1,0,2,2,2,1,1,1,1,2,0,2,2,2,2,2,2,0,2,0,2,2,1,2,1,
-  2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,
-  0,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,2,2,1,2,1,0,2,2,2,1,1,1,1,
-  2,2,2,0,2,2,2,2,2,2,0,2,2,0,2,0,2,1,2,2,2,2,2,2,1,2,1,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,1,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,1,1,1,2,2,2,2,1,1,1,1,
-  2,2,2,1,2,2,2,2,2,2,1,2,0,0,0,0,2,2,0,2,2,1,2,2,2,2,2,2,1,1,1,1,
-  2,0,0,0,2,2,2,2,0,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,0,0,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,0,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,1,
-  0,2,0,2,2,1,1,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,
-  2,0,2,0,2,1,2,1,0,2,0,2,2,2,1,2,2,0,2,0,2,2,2,2,0,2,0,2,2,2,1,2,
-  2,2,2,0,2,2,2,2,2,2,0,2,2,2,2,2,2,2,1,2,2,2,2,2,2,0,1,2,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  0,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,1,2,1,0,2,2,2,1,1,1,1,
-  2,0,2,0,2,1,2,2,0,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,1,2,2,
-  2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,2,1,2,1,
-  2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,0,0,2,2,2,1,2,2,2,
-  0,0,2,0,2,2,2,2,0,2,0,2,2,0,2,0,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,1,
-  2,2,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1,
-  0,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  2,0,0,2,2,2,2,2,0,2,0,2,2,2,2,2,1,0,1,2,2,2,2,1,0,2,2,2,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,0,2,2,0,2,0,2,1,2,2,2,2,2,2,2,2,0,2,2,1,2,2,
-  0,2,0,0,1,1,1,1,0,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,0,2,2,1,2,1,1,
-  2,2,0,2,2,1,2,2,2,2,2,2,1,2,2,2,2,0,2,2,2,2,2,2,0,2,0,2,1,2,1,1,
-  2,0,2,0,2,2,2,2,0,2,0,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,2,2,2,2,2,1,1,2,2,2,2,2,1,2,2,2,
-  2,0,2,2,2,1,2,1,0,2,2,2,2,2,1,2,2,0,2,0,2,2,2,2,0,2,0,2,2,1,2,2,
-  0,2,0,0,2,2,2,2,1,2,2,2,2,2,2,0,2,1,2,2,2,2,2,2,1,2,2,2,2,2,2,2,
-  0,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,1,0,2,2,
-  0,0,0,2,2,1,1,1,2,2,2,2,1,2,2,2,2,0,2,0,2,2,2,1,2,2,2,2,1,2,1,2,
-  0,0,0,0,2,2,2,2,2,2,0,2,2,1,2,2,2,1,2,1,2,2,2,2,1,2,1,2,0,2,2,2,
-  2,0,2,0,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  0,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,1,2,2,2,2,2,0,2,2,1,2,2,0,0,0,2,2,2,2,2,1,2,2,0,2,2,2,1,2,1,2,
-  2,0,2,0,2,2,2,2,0,2,0,2,2,1,2,2,0,2,0,0,2,2,2,2,2,2,2,2,2,1,2,2,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,1,
-  1,2,0,2,2,1,2,1,2,2,2,2,1,2,2,2,2,0,2,0,2,2,2,2,2,0,2,2,1,1,1,1,
-  0,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,1,2,1,
-  2,2,0,0,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
-  2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,
-  2,0,2,0,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,0,2,0,2,2,2,1,2,
-  2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,
-  2,0,2,0,2,2,2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,2,1,2,1,
-  2,2,2,2,2,1,2,1,0,2,0,2,2,2,2,2,2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,1,
-  2,0,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,0,
-  2,0,2,0,2,2,2,1,2,2,2,0,2,2,2,1,2,0,2,0,2,2,2,2,0,0,0,2,2,2,2,1,
-  2,0,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,
-  /* phase 3: offset=2816 */
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,0,2,2,2,1,2,0,2,2,2,1,2,2,2,2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,
-  2,2,2,1,2,2,2,0,1,1,1,1,0,0,0,0,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,0,0,0,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,
-  2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,2,0,2,0,2,1,2,1,
-  2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,
-  2,0,2,2,2,1,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,0,2,0,1,1,2,1,
-  2,2,2,0,2,2,2,1,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,
-  0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1,
-  2,0,0,2,2,1,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,1,1,1,2,0,0,0,
-  2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2,2,2,2,0,2,2,2,1,2,0,2,0,2,1,2,1,
-  2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,
-  2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,0,2,0,2,1,2,1,0,0,2,0,1,1,2,1,
-  2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,0,0,0,2,1,1,1,
-  2,2,2,1,2,2,2,0,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2,
-  2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,
-  2,0,2,2,2,1,2,2,0,0,2,0,1,1,2,1,2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,
-  2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,0,0,0,1,1,1,1,
-  2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,1,0,2,2,0,1,2,
-  2,2,2,1,2,2,2,0,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,
-  2,1,2,1,2,0,2,0,1,2,1,1,0,2,0,0,0,0,2,1,1,1,2,0,0,0,0,0,1,1,1,1,
-  2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,0,2,1,2,1,2,0,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,0,2,2,2,1,2,2,2,0,0,2,2,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,
-  2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,0,0,0,0,1,1,1,1,
-  2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,0,0,0,2,1,1,1,
-  2,2,2,0,2,2,2,1,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,
-  2,0,2,2,2,1,2,2,2,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,1,2,1,2,0,2,0,1,2,1,1,0,2,0,0,2,0,2,2,2,1,2,2,0,2,1,2,1,2,0,2,
-  2,2,2,1,2,2,2,0,2,2,1,2,2,2,0,2,2,1,2,2,2,0,2,2,2,2,0,2,2,2,1,2,
-  0,0,2,0,1,1,2,1,0,0,1,0,1,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,0,2,2,2,1,1,2,2,2,0,2,2,2,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,0,0,2,2,1,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,
-  2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,2,2,1,2,2,2,0,2,1,2,1,2,0,2,0,
-  2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1,2,0,0,0,2,1,1,1,
-  2,2,2,2,2,2,2,2,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,1,2,1,2,0,2,0,2,0,2,2,2,1,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,1,1,1,2,0,0,0,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1,
-  2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2,
-  2,1,2,1,2,0,2,0,2,1,2,2,2,0,2,2,2,2,2,0,2,2,2,1,2,0,2,0,2,1,2,1,
-  2,0,2,0,2,1,2,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,
-  2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,0,1,0,0,1,0,1,1,
-  2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2,2,1,0,2,0,2,2,2,1,2,2,2,
-  2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,
-  2,0,2,0,2,1,2,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,
-  0,2,0,0,1,2,1,1,2,0,0,0,2,1,1,1,2,2,2,2,2,2,2,2,1,0,1,2,0,1,0,2,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,1,2,2,2,0,2,2,1,1,2,2,0,0,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,1,2,1,2,0,2,0,2,1,2,2,2,0,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,1,2,2,2,0,2,2,2,
-  2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,2,
-  0,0,0,0,1,1,1,1,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,2,0,2,2,2,1,2,
-  2,0,2,0,2,1,2,1,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,
-  0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,1,2,2,2,0,1,1,2,1,0,0,2,0,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,0,2,2,2,1,2,
-  2,0,2,0,2,1,2,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,
-  0,2,0,0,1,2,1,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1,2,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,0,2,1,1,1,2,0,0,2,2,2,1,2,2,2,
-  2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1,
-  0,0,2,2,1,1,2,2,0,2,1,2,1,2,0,2,2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2,
-  2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,
-  2,2,0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2,2,2,2,2,2,2,2,2,0,0,2,2,1,1,
-  2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1,
-  2,2,2,0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,1,1,1,2,0,0,0,2,
-  2,2,2,2,2,2,2,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,
-  2,0,2,0,2,1,2,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1,
-  2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2,2,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,
-  2,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,0,2,0,2,1,2,1,2,1,2,0,2,0,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,0,2,0,2,1,2,1,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,
-  2,0,2,1,2,1,2,0,0,2,1,2,1,2,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,0,2,0,2,1,2,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,
-  2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,1,2,1,2,0,2,0,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,
-  2,0,2,0,2,1,2,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-};
diff --git a/converter/other/jbig/jbigtopnm.c b/converter/other/jbig/jbigtopnm.c
index 7a6e95c1..733ba227 100644
--- a/converter/other/jbig/jbigtopnm.c
+++ b/converter/other/jbig/jbigtopnm.c
@@ -231,7 +231,7 @@ int main (int argc, char **argv)
         pm_error("Problem while reading input file '%s", fnin);
     if (result != JBG_EOK && result != JBG_EOK_INTR) 
         pm_error("Problem with input file '%s': %s\n", 
-                 fnin, jbg_strerror(result, JBG_EN));
+                 fnin, jbg_strerror(result));
     if (plane >= 0 && jbg_dec_getplanes(&s) <= plane) 
         pm_error("Image has only %d planes!\n", jbg_dec_getplanes(&s));
 
diff --git a/converter/other/jpeg2000/Makefile b/converter/other/jpeg2000/Makefile
index 7b008906..009232d7 100644
--- a/converter/other/jpeg2000/Makefile
+++ b/converter/other/jpeg2000/Makefile
@@ -40,16 +40,17 @@ endif
 
 ifneq ($(JASPERHDR_DIR),NONE)
   ifneq ($(JASPERLIB_USE),NONE)
-    BINARIES = pamtojpeg2k jpeg2ktopam
+    PORTBINARIES = pamtojpeg2k jpeg2ktopam
   endif
 endif
 
+BINARIES = $(PORTBINARIES)
 
 OBJECTS = $(BINARIES:%=%.o)
 MERGE_OBJECTS = $(BINARIES:%=%.o2) 
 ifeq ($(JASPERLIB),$(INTERNAL_JASPERLIB))
   # MERGE_OBJECTS contains relative paths, so $(INTERNAL_JASPERLIB) had better
-  # be relative to the current relative to the current directory.
+  # be relative to the current directory.
   MERGE_OBJECTS += $(JASPERLIB)
 endif
 MERGEBINARIES = $(BINARIES)
@@ -59,12 +60,10 @@ all: $(BINARIES)
 
 include $(SRCDIR)/common.mk
 
-LIBOPTS = $(shell $(LIBOPT) $(JASPERLIB_USE) $(NETPBMLIB))
+LIBOPTS = $(shell $(LIBOPT) $(JASPERLIB_USE))
 
-$(BINARIES): %: %.o $(JASPERLIB_DEP) $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $< \
-	  $(LIBOPTS) $(JASPERDEPLIBS) $(MATHLIB) $(RPATH) \
-	  $(LDFLAGS) $(LDLIBS) $(LADD)
+$(BINARIES): %: %.o $(JASPERLIB_DEP) $(LIBOPT)
+$(BINARIES): LDFLAGS_TARGET = $(LIBOPTS) $(JASPERDEPLIBS)
 
 $(INTERNAL_JASPERLIB): $(BUILDDIR)/$(SUBDIR)/libjasper FORCE
 	$(MAKE) -f $(SRCDIR)/$(SUBDIR)/libjasper/Makefile \
diff --git a/converter/other/jpeg2000/jpeg2ktopam.c b/converter/other/jpeg2000/jpeg2ktopam.c
index 49479774..858c0fa4 100644
--- a/converter/other/jpeg2000/jpeg2ktopam.c
+++ b/converter/other/jpeg2000/jpeg2ktopam.c
@@ -13,13 +13,14 @@
 #define _XOPEN_SOURCE 600
 #include <string.h>
 
+#include <jasper/jasper.h>
+
 #include "pm_c_util.h"
 #include "pam.h"
 #include "shhopt.h"
 #include "nstring.h"
 #include "mallocvar.h"
 
-#include <jasper/jasper.h>
 #include "libjasper_compat.h"
 
 enum compmode {COMPMODE_INTEGER, COMPMODE_REAL};
diff --git a/converter/other/jpeg2000/libjasper/base/jas_image.c b/converter/other/jpeg2000/libjasper/base/jas_image.c
index 8d62b48d..903b45c6 100644
--- a/converter/other/jpeg2000/libjasper/base/jas_image.c
+++ b/converter/other/jpeg2000/libjasper/base/jas_image.c
@@ -623,7 +623,7 @@ int jas_image_getfmt(jas_stream_t *in)
 	int found;
 	int i;
 
-	/* Check for data in each of the supported formats. */
+	/* Check for data in each of the formats we know. */
 	found = 0;
 	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i,
 	  ++fmtinfo) {
diff --git a/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h b/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h
index 558f4368..6e914efd 100644
--- a/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h
+++ b/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h
@@ -171,9 +171,9 @@ extern "C" {
 
 #define	JAS_IMAGE_CT_GRAY_Y	0
 
-/******************************************************************************\
+/*****************************************************************************\
 * Image class and supporting classes.
-\******************************************************************************/
+\*****************************************************************************/
 
 /* Image component class. */
 
@@ -294,7 +294,7 @@ typedef struct {
 \******************************************************************************/
 
 #define	JAS_IMAGE_MAXFMTS	32
-/* The maximum number of image data formats supported. */
+/* The maximum number of image data formats we can handle. */
 
 /* Image format-dependent operations. */
 
@@ -530,57 +530,57 @@ int jas_image_getfmt(jas_stream_t *in);
 * Image format-dependent operations.
 \******************************************************************************/
 
-#if !defined(EXCLUDE_JPG_SUPPORT)
-/* Format-dependent operations for JPG support. */
+#if !defined(EXCLUDE_JPG_CAPABILITY)
+/* Format-dependent operations for JPG capability. */
 jas_image_t *jpg_decode(jas_stream_t *in, char *optstr);
 int jpg_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int jpg_validate(jas_stream_t *in);
 #endif
 
-#if !defined(EXCLUDE_MIF_SUPPORT)
-/* Format-dependent operations for MIF support. */
+#if !defined(EXCLUDE_MIF_CAPABILITY)
+/* Format-dependent operations for MIF capability. */
 jas_image_t *mif_decode(jas_stream_t *in, char *optstr);
 int mif_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int mif_validate(jas_stream_t *in);
 #endif
 
-#if !defined(EXCLUDE_PNM_SUPPORT)
-/* Format-dependent operations for PNM support. */
+#if !defined(EXCLUDE_PNM_CAPABILITY)
+/* Format-dependent operations for PNM capability. */
 jas_image_t *pnm_decode(jas_stream_t *in, char *optstr);
 int pnm_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int pnm_validate(jas_stream_t *in);
 #endif
 
-#if !defined(EXCLUDE_RAS_SUPPORT)
-/* Format-dependent operations for Sun Rasterfile support. */
+#if !defined(EXCLUDE_RAS_CAPABILITY)
+/* Format-dependent operations for Sun Rasterfile capability. */
 jas_image_t *ras_decode(jas_stream_t *in, char *optstr);
 int ras_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int ras_validate(jas_stream_t *in);
 #endif
 
-#if !defined(EXCLUDE_BMP_SUPPORT)
-/* Format-dependent operations for BMP support. */
+#if !defined(EXCLUDE_BMP_CAPABILITY)
+/* Format-dependent operations for BMP capability. */
 jas_image_t *bmp_decode(jas_stream_t *in, char *optstr);
 int bmp_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int bmp_validate(jas_stream_t *in);
 #endif
 
-#if !defined(EXCLUDE_JP2_SUPPORT)
-/* Format-dependent operations for JP2 support. */
+#if !defined(EXCLUDE_JP2_CAPABILITY)
+/* Format-dependent operations for JP2 capability. */
 jas_image_t *jp2_decode(jas_stream_t *in, char *optstr);
 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_SUPPORT)
-/* Format-dependent operations for JPEG-2000 code stream support. */
+#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);
 int jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int jpc_validate(jas_stream_t *in);
 #endif
 
-#if !defined(EXCLUDE_PGX_SUPPORT)
-/* Format-dependent operations for PGX support. */
+#if !defined(EXCLUDE_PGX_CAPABILITY)
+/* Format-dependent operations for PGX capability. */
 jas_image_t *pgx_decode(jas_stream_t *in, char *optstr);
 int pgx_encode(jas_image_t *image, jas_stream_t *out, char *optstr);
 int pgx_validate(jas_stream_t *in);
diff --git a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c
index aaebf411..91ce6c51 100644
--- a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c
+++ b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c
@@ -297,9 +297,9 @@ jas_image_t *jp2_decode(jas_stream_t *in, char *optstr)
 		jas_eprintf("warning: component data type mismatch\n");
 	}
 
-	/* Is the compression type supported? */
+	/* Can we handle the compression type? */
 	if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) {
-		jas_eprintf("error: unsupported compression type\n");
+		jas_eprintf("error: not capable of this compression type\n");
 		goto error;
 	}
 
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c b/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c
index ffe6aab5..559f36cf 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c
@@ -1461,8 +1461,6 @@ static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in
 
 static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
 {
-    /* If this function is called, we are trying to write an unsupported
-      type of marker segment.  Return with an error indication.  */
     return -1;
 }
 
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c
index b52dcc27..d17e9aa3 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c
@@ -346,7 +346,7 @@ static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image)
         if (jas_image_cmptbrx(image, cmptno) + jas_image_cmpthstep(image, cmptno) <=
           jas_image_brx(image) || jas_image_cmptbry(image, cmptno) +
           jas_image_cmptvstep(image, cmptno) <= jas_image_bry(image)) {
-            fprintf(stderr, "unsupported image type\n");
+            fprintf(stderr, "We don't know how to interpret this image type\n");
             goto error;
         }
         /* Note: We ought to be calculating the LCMs here.  Fix some day. */
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c b/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c
index 1d41d5c5..80bc5aa5 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c
@@ -900,8 +900,8 @@ static void jpc_ns_analyze(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x)
 			startptr += interstep;
 		}
 	} else {
-		/* The reversible integer-to-integer mode is not supported
-		  for this transform. */
+		/* The reversible integer-to-integer mode is not valid for this
+		  transform. */
 		abort();
 	}
 }
@@ -973,8 +973,8 @@ static void jpc_ns_synthesize(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x)
 			startptr += interstep;
 		}
 	} else {
-		/* The reversible integer-to-integer mode is not supported
-		  for this transform. */
+		/* The reversible integer-to-integer mode is not valid
+           for this transform. */
 		abort();
 	}
 }
diff --git a/converter/other/jpeg2000/pamtojpeg2k.c b/converter/other/jpeg2000/pamtojpeg2k.c
index 15ea0f31..349018e1 100644
--- a/converter/other/jpeg2000/pamtojpeg2k.c
+++ b/converter/other/jpeg2000/pamtojpeg2k.c
@@ -13,13 +13,14 @@
 #define _XOPEN_SOURCE 600
 #include <string.h>
 
+#include <jasper/jasper.h>
+
 #include "pm_c_util.h"
 #include "pam.h"
 #include "shhopt.h"
 #include "nstring.h"
 #include "mallocvar.h"
 
-#include <jasper/jasper.h>
 #include "libjasper_compat.h"
 
 
diff --git a/converter/other/jpegtopnm.c b/converter/other/jpegtopnm.c
index f09cd04f..ab3b18e5 100644
--- a/converter/other/jpegtopnm.c
+++ b/converter/other/jpegtopnm.c
@@ -652,19 +652,20 @@ print_exif_info(struct jpeg_marker_struct const marker) {
    Dump as informational messages the contents of the Jpeg miscellaneous
    marker 'marker', assuming it is an Exif header.
 -----------------------------------------------------------------------------*/
-    ImageInfo_t imageInfo;
+    bool const wantTagTrace = false;
+    exif_ImageInfo imageInfo;
     const char * error;
 
     assert(marker.data_length >= 6);
 
-    process_EXIF(marker.data+6, marker.data_length-6, 
-                 &imageInfo, FALSE, &error);
+    exif_parse(marker.data+6, marker.data_length-6, 
+               &imageInfo, wantTagTrace, &error);
 
     if (error) {
         pm_message("EXIF header is invalid.  %s", error);
         pm_strfree(error);
     } else
-        ShowImageInfo(&imageInfo);
+        exif_showImageInfo(&imageInfo, stderr);
 }
 
 
@@ -700,8 +701,7 @@ dump_exif(struct jpeg_decompress_struct const cinfo) {
 
     found_one = FALSE;  /* initial value */
 
-    for (markerP = cinfo.marker_list;
-         markerP; markerP = markerP->next) 
+    for (markerP = cinfo.marker_list; markerP; markerP = markerP->next) 
         if (is_exif(*markerP)) {
             pm_message("EXIF INFO:");
             print_exif_info(*markerP);
diff --git a/converter/other/pamtosvg/Makefile b/converter/other/pamtosvg/Makefile
index 8b033020..83f150d0 100644
--- a/converter/other/pamtosvg/Makefile
+++ b/converter/other/pamtosvg/Makefile
@@ -7,26 +7,13 @@ VPATH=.:$(SRCDIR)/$(SUBDIR)
 
 include $(BUILDDIR)/config.mk
 
-BINARIES = pamtosvg
+PORTBINARIES = pamtosvg
 
-PAMTOSVG_OBJECTS = \
-	pamtosvg.o \
-	output-svg.o \
-	fit.o \
-	spline.o \
-	curve.o \
-	vector.o \
-	epsilon-equal.o \
-	autotrace.o \
-	pxl-outline.o \
-	bitmap.o \
-	thin-image.o \
-	logreport.o \
-	exception.o \
-	image-proc.o \
+BINARIES = $(PORTBINARIES)
+
+MERGEBINARIES = $(BINARIES)
 
-MERGE_OBJECTS = \
-	pamtosvg.o2 \
+ADDL_OBJECTS = \
 	output-svg.o \
 	fit.o \
 	spline.o \
@@ -41,15 +28,12 @@ MERGE_OBJECTS = \
 	exception.o \
 	image-proc.o \
 
-OBJECTS = $(PAMTOSVG_OBJECTS)
+OBJECTS = pamtosvg.o $(ADDL_OBJECTS)
 
-MERGEBINARIES = $(BINARIES)
+MERGE_OBJECTS = pamtosvg.o2 $(ADDL_OBJECTS)
 
 all: $(BINARIES)
 
 include $(SRCDIR)/common.mk
 
-pamtosvg: $(PAMTOSVG_OBJECTS) $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $(PAMTOSVG_OBJECTS) \
-	  $(shell $(LIBOPT) $(NETPBMLIB)) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
+pamtosvg: $(ADDL_OBJECTS)
diff --git a/converter/other/pamtosvg/bitmap.h b/converter/other/pamtosvg/bitmap.h
index 7334f138..b979e0c0 100644
--- a/converter/other/pamtosvg/bitmap.h
+++ b/converter/other/pamtosvg/bitmap.h
@@ -36,7 +36,7 @@ at_bitmap_type * at_bitmap_new(unsigned short width,
 			       unsigned int planes);
 at_bitmap_type * at_bitmap_copy(at_bitmap_type * src);
 
-/* We have to export functions that supports internal datum 
+/* We have to export functions that allows internal datum 
    access. Such functions might be useful for 
    at_bitmap_new user. */
 unsigned short at_bitmap_get_width (at_bitmap_type * bitmap);
diff --git a/converter/other/pamtosvg/image-proc.c b/converter/other/pamtosvg/image-proc.c
index b044b547..d025ee1e 100644
--- a/converter/other/pamtosvg/image-proc.c
+++ b/converter/other/pamtosvg/image-proc.c
@@ -330,7 +330,7 @@ binarize(bitmap_type *bitmap)
     }
     else
     {
-	    WARNING1("binarize: %u-plane images are not supported", spp);
+	    WARNING1("binarize: don't know how to interpret %u-plane images", spp);
     }
 }
 
diff --git a/converter/other/pamtosvg/thin-image.c b/converter/other/pamtosvg/thin-image.c
index 86d1037c..364f67cc 100644
--- a/converter/other/pamtosvg/thin-image.c
+++ b/converter/other/pamtosvg/thin-image.c
@@ -189,7 +189,7 @@ thin_image(bitmap_type *image, bool bgSpec, pixel bg,
 
 	default:
 	{
-	  LOG1 ("thin_image: %u-plane images are not supported", spp);
+	  LOG1 ("thin_image: Don't know how to interpret %u-plane images", spp);
 	  at_exception_fatal(exp, "thin_image: wrong plane images are passed");
 	  goto cleanup;
 	}
diff --git a/converter/other/pamtotiff.c b/converter/other/pamtotiff.c
index 0206678d..f2cc0e2b 100644
--- a/converter/other/pamtotiff.c
+++ b/converter/other/pamtotiff.c
@@ -53,16 +53,19 @@
 #define COMPRESSION_ADOBE_DEFLATE 8
 #endif
 
-struct sizeset {
+typedef struct {
     bool b1, b2, b4, b8;
-};
+} SizeSet;
 
+typedef enum { TMPFILE, DIRECT_CREATE, DIRECT_APPEND } WriteMethod;
 
-struct cmdlineInfo {
+typedef enum { MUST_EXIST, MAY_CREATE } CreatePolicy;
+
+typedef struct {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *input_filespec;  /* Filespecs of input files */
+    const char * inputFileName;
     int compression;
         /* COMPRESSION Tiff tag value, that corresponds to the compression
            option the user specified, or -1 if he didn't specify any.
@@ -79,13 +82,14 @@ struct cmdlineInfo {
     float xresolution; /* XRESOLUTION Tiff tag value or -1 for none */
     float yresolution; /* YRESOLUTION Tiff tag value or -1 for none */
     int resolutionunit;  /* RESOLUTIONUNIT Tiff tag value */
-    struct sizeset indexsizeAllowed;
+    SizeSet indexsizeAllowed;
     /* Which bit widths are allowable in a raster of palette indices */
     unsigned int verbose;
-    unsigned int append;
+    WriteMethod writeMethod;  /* Output mode */
+    const char * output; /* -output option value.  NULL if none. */
     float resolution;  /* X and Y resolution */
     struct optNameValue * taglist;
-};
+} CmdlineInfo;
 
 
 
@@ -96,7 +100,7 @@ validateTagList(struct optNameValue const taglist[]) {
     for (i = 0; taglist[i].name; ++i) {
         const char * const tagName = taglist[i].name;
         const tagDefinition * tagDefP = tagDefFind(tagName);
-        
+
         if (!tagDefP)
             pm_error("Unknown tag name '%s'", tagName);
         else {
@@ -131,9 +135,9 @@ validateTagList(struct optNameValue const taglist[]) {
 
 
 static void
-parseCommandLine(int                        argc,
-                 char **              const argv,
-                 struct cmdlineInfo * const cmdlineP) {
+parseCommandLine(int                 argc,
+                 const char ** const argv,
+                 CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
@@ -147,8 +151,9 @@ parseCommandLine(int                        argc,
     char * indexbits;
     char * resolutionunit;
 
-    unsigned int predictorSpec, rowsperstripSpec, xresolutionSpec,
-        yresolutionSpec, indexbitsSpec, resolutionunitSpec, tagSpec;
+    unsigned int appendSpec, outputSpec, predictorSpec, rowsperstripSpec,
+                 xresolutionSpec, yresolutionSpec, indexbitsSpec,
+      resolutionunitSpec, tagSpec;
 
     unsigned int option_def_index;
 
@@ -156,7 +161,6 @@ parseCommandLine(int                        argc,
 
     option_def_index = 0;   /* incremented by OPTENT3 */
     OPTENT3(0, "verbose",      OPT_FLAG,   NULL, &cmdlineP->verbose,       0);
-    OPTENT3(0, "append",       OPT_FLAG,   NULL, &cmdlineP->append,        0);
     OPTENT3(0, "none",         OPT_FLAG,   NULL, &none,                    0);
     OPTENT3(0, "packbits",     OPT_FLAG,   NULL, &packbits,                0);
     OPTENT3(0, "lzw",          OPT_FLAG,   NULL, &lzw,                     0);
@@ -174,17 +178,20 @@ parseCommandLine(int                        argc,
     OPTENT3(0, "mw",           OPT_FLAG,   NULL, &cmdlineP->miniswhite,    0);
     OPTENT3(0, "truecolor",    OPT_FLAG,   NULL, &cmdlineP->truecolor,     0);
     OPTENT3(0, "color",        OPT_FLAG,   NULL, &cmdlineP->color,         0);
-    OPTENT3(0, "predictor",    OPT_UINT,   &cmdlineP->predictor,    
+    OPTENT3(0, "append",       OPT_FLAG,   NULL, &appendSpec,       0);
+    OPTENT3(0, "output",       OPT_STRING, &cmdlineP->output,
+            &outputSpec,       0);
+    OPTENT3(0, "predictor",    OPT_UINT,   &cmdlineP->predictor,
             &predictorSpec,    0);
-    OPTENT3(0, "rowsperstrip", OPT_UINT,   &cmdlineP->rowsperstrip, 
+    OPTENT3(0, "rowsperstrip", OPT_UINT,   &cmdlineP->rowsperstrip,
             &rowsperstripSpec, 0);
-    OPTENT3(0, "xresolution",  OPT_FLOAT,  &cmdlineP->xresolution,  
+    OPTENT3(0, "xresolution",  OPT_FLOAT,  &cmdlineP->xresolution,
             &xresolutionSpec,  0);
-    OPTENT3(0, "yresolution",  OPT_FLOAT,  &cmdlineP->yresolution,  
+    OPTENT3(0, "yresolution",  OPT_FLOAT,  &cmdlineP->yresolution,
             &yresolutionSpec,  0);
     OPTENT3(0, "resolutionunit", OPT_STRING, &resolutionunit,
             &resolutionunitSpec,    0);
-    OPTENT3(0, "indexbits",    OPT_STRING,   &indexbits, 
+    OPTENT3(0, "indexbits",    OPT_STRING,   &indexbits,
             &indexbitsSpec,    0);
     OPTENT3(0, "tag",          OPT_NAMELIST, &cmdlineP->taglist, &tagSpec, 0);
 
@@ -192,14 +199,14 @@ parseCommandLine(int                        argc,
     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);
     /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (none + packbits + lzw + g3 + g4 + flate + adobeflate > 1)
         pm_error("You specified more than one compression option.  "
                  "Only one of -none, -packbits, -lze, -g3, and -g4 "
                  "is allowed.");
-    
+
     if (none)
         cmdlineP->compression = COMPRESSION_NONE;
     else if (packbits)
@@ -216,7 +223,7 @@ parseCommandLine(int                        argc,
         cmdlineP->compression = COMPRESSION_DEFLATE;
     else
         cmdlineP->compression = COMPRESSION_NONE;
-    
+
     if (msb2lsb + lsb2msb > 1)
         pm_error("You specified both -msb2lsb and -lsb2msb.  "
                  "These are conflicting options.");
@@ -225,9 +232,9 @@ parseCommandLine(int                        argc,
         cmdlineP->fillorder = FILLORDER_MSB2LSB;
     else if (lsb2msb)
         cmdlineP->fillorder = FILLORDER_LSB2MSB;
-    else 
+    else
         cmdlineP->fillorder = FILLORDER_MSB2LSB;
-    
+
 
     if (cmdlineP->miniswhite && cmdlineP->minisblack)
         pm_error("You cannot specify both -miniswhite and -minisblack");
@@ -238,9 +245,17 @@ parseCommandLine(int                        argc,
     if (fill)
         cmdlineP->g3options |= GROUP3OPT_FILLBITS;
 
+    if (outputSpec) {
+        if (appendSpec)
+            cmdlineP->writeMethod = DIRECT_APPEND;
+        else
+            cmdlineP->writeMethod = DIRECT_CREATE;
+    } else
+        cmdlineP->writeMethod = TMPFILE;
+
     if (predictorSpec) {
         if (cmdlineP->predictor != 1 && cmdlineP->predictor != 2)
-            pm_error("-predictor may be only 1 or 2.  You specified %d.", 
+            pm_error("-predictor may be only 1 or 2.  You specified %d.",
                      cmdlineP->predictor);
     } else
         cmdlineP->predictor = -1;
@@ -318,13 +333,13 @@ parseCommandLine(int                        argc,
         cmdlineP->taglist[0].value = NULL;
     }
 
-    if (argc-1 == 0) 
-        cmdlineP->input_filespec = "-";
+    if (argc-1 == 0)
+        cmdlineP->inputFileName = "-";
     else if (argc-1 != 1)
         pm_error("Program takes zero or one argument (filename).  You "
                  "specified %d", argc-1);
     else
-        cmdlineP->input_filespec = argv[1];
+        cmdlineP->inputFileName = argv[1];
 }
 
 
@@ -346,9 +361,9 @@ fillRowOfSubBytePixels(struct pam *    const pamP,
     int bitshift;
         /* The number of bits we have to shift a pixel value left to line
            it up with where the current pixel goes in the current byte of
-           the output buffer.  
+           the output buffer.
         */
-    int const firstbitshift = 
+    int const firstbitshift =
         (fillorder == FILLORDER_MSB2LSB) ? 8 - bitspersample : 0;
         /* The value of 'bitshift' for the first pixel into a
            byte of the output buffer.  (MSB2LSB is normal).
@@ -363,7 +378,7 @@ fillRowOfSubBytePixels(struct pam *    const pamP,
         /* The under-construction value of the byte pointed to by
            tP, above.
         */
-                
+
     bitshift = firstbitshift;
     byte = 0;
     for (col = 0, tP = buf; col < pamP->width; ++col) {
@@ -372,7 +387,7 @@ fillRowOfSubBytePixels(struct pam *    const pamP,
             s = tuplerow[col][0];
             if (pamP->maxval != tiff_maxval )
                 s = (long) s * tiff_maxval / pamP->maxval;
- 
+
             if (photometric == PHOTOMETRIC_MINISWHITE)
                 s = tiff_maxval - s;
         } else {
@@ -448,7 +463,7 @@ fillRowOfWholeBytePixels(struct pam *    const pamP,
     unsigned int col;
     unsigned char * tP;
     unsigned int planes;
-    
+
     if (photometric == PHOTOMETRIC_RGB)
         planes = pamP->depth;
     else
@@ -465,18 +480,18 @@ fillRowOfWholeBytePixels(struct pam *    const pamP,
             /* Advances tP */
         }
     }
-} 
+}
 
 
 
 static void
 writeScanLines(struct pam *   const pamP,
-               TIFF *         const tif, 
+               TIFF *         const tif,
                tuplehash      const cht,
                unsigned short const tiffMaxval,
-               unsigned short const bitspersample, 
+               unsigned short const bitspersample,
                unsigned short const photometric,
-               int            const bytesperrow, 
+               int            const bytesperrow,
                int            const fillorder) {
 /*----------------------------------------------------------------------------
    Write out the raster for the input image described by 'pamP', whose
@@ -510,7 +525,7 @@ writeScanLines(struct pam *   const pamP,
         pm_error("can't allocate memory for row buffer");
 
     tuplerow = pnm_allocpamrow(pamP);
-    
+
     for (row = 0; row < pamP->height; ++row) {
         int col;
 
@@ -532,9 +547,9 @@ writeScanLines(struct pam *   const pamP,
                 for (col = 0; col < pamP->width; ++col) {
                     int si;
                     int found;
-                    
+
                     pnm_lookuptuple(pamP, cht, tuplerow[col], &found, &si);
-                    
+
                     if (!found)
                         pm_error("INTERNAL ERROR.  We made a color map, and a "
                                  "color map we need is not in it!  "
@@ -558,12 +573,12 @@ writeScanLines(struct pam *   const pamP,
 
 
 static void
-analyzeColorsInRgbInput(struct pam *        const pamP,
-                        struct cmdlineInfo  const cmdline,
-                        int                 const maxcolors, 
-                        tupletable *        const chvP, 
-                        unsigned int *      const colorsP, 
-                        bool *              const grayscaleP) {
+analyzeColorsInRgbInput(struct pam *   const pamP,
+                        CmdlineInfo    const cmdline,
+                        int            const maxcolors,
+                        tupletable *   const chvP,
+                        unsigned int * const colorsP,
+                        bool *         const grayscaleP) {
 /*----------------------------------------------------------------------------
    Same as analyzeColors(), except assuming input image has R/G/B tuples.
 -----------------------------------------------------------------------------*/
@@ -582,7 +597,7 @@ analyzeColorsInRgbInput(struct pam *        const pamP,
             grayscale = FALSE;
         } else {
             unsigned int i;
-            pm_message("%u color%s found", 
+            pm_message("%u color%s found",
                        *colorsP, *colorsP == 1 ? "" : "s");
             grayscale = TRUE;  /* initial assumption */
             for (i = 0; i < *colorsP && grayscale; ++i) {
@@ -615,15 +630,15 @@ analyzeColorsInRgbInput(struct pam *        const pamP,
 
 
 static void
-analyzeColors(struct pam *        const pamP,
-              struct cmdlineInfo  const cmdline,
-              int                 const maxcolors, 
-              tupletable *        const chvP, 
-              unsigned int *      const colorsP, 
-              bool *              const grayscaleP) {
+analyzeColors(struct pam *   const pamP,
+              CmdlineInfo    const cmdline,
+              int            const maxcolors,
+              tupletable *   const chvP,
+              unsigned int * const colorsP,
+              bool *         const grayscaleP) {
 /*----------------------------------------------------------------------------
    Analyze the colors in the input image described by 'pamP', whose file
-   is positioned to the raster. 
+   is positioned to the raster.
 
    If the colors, combined with command line options 'cmdline', indicate
    a colormapped TIFF should be generated, return as *chvP the address
@@ -652,13 +667,13 @@ analyzeColors(struct pam *        const pamP,
 
 static void
 computeRasterParm(struct pam *     const pamP,
-                  tupletable       const chv, 
-                  int              const colors, 
+                  tupletable       const chv,
+                  int              const colors,
                   bool             const grayscale,
                   int              const compression,
                   bool             const minisblack,
                   bool             const miniswhite,
-                  struct sizeset   const indexsizeAllowed,
+                  SizeSet          const indexsizeAllowed,
                   unsigned short * const samplesperpixelP,
                   unsigned short * const bitspersampleP,
                   unsigned short * const photometricP,
@@ -679,7 +694,7 @@ computeRasterParm(struct pam *     const pamP,
        option.  It is not clear why we don't use bits per pixel < 8
        for RGB images.  Note that code to handle maxvals <= 255 was
        written long before maxval > 255 was possible and there are
-       backward compatibility requirements.  
+       backward compatibility requirements.
     */
 
     if (pamP->depth == 1 && pamP->maxval == 1) {
@@ -693,7 +708,7 @@ computeRasterParm(struct pam *     const pamP,
     } else {
         if (chv) {
             *samplesperpixelP = 1;  /* Pixel is just the one index value */
-            *bitspersampleP = 
+            *bitspersampleP =
                 colors <=   2 && indexsizeAllowed.b1 ? 1 :
                 colors <=   4 && indexsizeAllowed.b2 ? 2 :
                 colors <=  16 && indexsizeAllowed.b4 ? 4 :
@@ -746,18 +761,53 @@ computeRasterParm(struct pam *     const pamP,
 
 
 
-static void
-validateSeekableOutputFile(int          const ofd,
-                           const char * const outFileName) {
 /*----------------------------------------------------------------------------
-   Validate that the file attached to file descriptor 'ofd' is capable
-   of seeking.  If not, fail the program.
+  WRITE MODES
+  -----------
+  
+  The Tiff library does all output.  There are several issues:
+  
+    1) The manner of output is opaque to the library client.  I.e.  we cannot
+       see or control it.
+
+    2) The output file must be random-access.
+
+    3) The output file must be writable and readable for multiple-image
+       streams.  (This includes append operations.)
+
+    4) The Tiff library produces unhelpful error messages when the above
+       conditions are not met.
+  
+  We provide two modes for output:
+  
+  1. Tmpfile mode (default)
+  
+     We have the Tiff library direct output to an unnamed temporary file we
+     create which is seekable and readable.  When output is complete, we copy
+     the file's contents to Standard Output.
+  
+  2. Direct mode (specified with -output)
+  
+     We have the Tiff library write output to the specified file.  As the Tiff
+     library requires taht it be be seekable and readable, we fail the program
+     rather than ask the Tiff library to use the file if it does not meet
+     these requirements.
+  
+     Direct mode is further divided into append and create.  They are the same
+     except that in append mode, we insist that the file already exist,
+     whereas with create mode, we create it if necessary.  In either case, if
+     the file already exists, he Tiff library appends the output to it.
+-----------------------------------------------------------------------------*/
+
+
 
-   This is useful because the TIFF library requires seekable output and
-   fails with an unhelpful error message about a file I/O error if it is
-   not.  We, on the other hand, give a helpful error message.
+static bool
+fileIsSeekable(int          const ofd,
+               const char * const outFileName) {
+/*----------------------------------------------------------------------------
+  The file represented by 'ofd' iscapable of seeking.
 
-   We leave the file positioned to the beginning.
+  As a side effect, we position the file to the beginning.
 -----------------------------------------------------------------------------*/
     int rc;
 
@@ -771,44 +821,160 @@ validateSeekableOutputFile(int          const ofd,
     */
     lseek(ofd, 1, SEEK_SET);
     rc = lseek(ofd, 0, SEEK_SET);
-            
-    if (rc < 0)
-        pm_error("Output file (%s) is not seekable.  lseek() returned "
-                 "errno %d (%s).  "
-                 "The TIFF library can write only to "
-                 "a seekable file.", 
-                 outFileName, errno, strerror(errno));
+
+    return rc >= 0;
+
 }
 
 
 
 static void
-createTiffGenerator(int          const ofd, 
-                    const char * const outFileName,
-                    bool         const append,
-                    TIFF **      const tifPP) {
+validateReadableOutputFile(int const ofd) {
+/*----------------------------------------------------------------------------
+  Validate that file 'ofd' is readable and fail the program if it isn't.
 
-    const char * option;
+  This is useful because there are situations in which the TIFF library must
+  read the output file and if it can't, it fails with an unhelpful error
+  message about a file I/O error.  We, on the other hand, produce a helpful
+  error message.
+-----------------------------------------------------------------------------*/
+#if !MSVCRT
 
-    validateSeekableOutputFile(ofd, outFileName);
+    int flags;
 
-    if (append)
-        option = "a";
+    flags = fcntl(ofd, F_GETFL);
+
+    if (flags < 0) {
+        /* We couldn't get the flags.  So just assume the file's OK */
+    } else {
+        if ((flags & O_RDONLY) || (flags & O_RDWR)) {
+            /* File is readable.  All is well. */
+        } else
+            pm_error("Output is not opened for reading.  "
+                     "In order to create a multi-image TIFF stream, "
+                     "output must be both readable and writable.");
+    }
+#endif
+}
+
+
+
+static void
+createTiffGeneratorDirect(const char * const outputFileName,
+                          CreatePolicy const createPolicy,
+                          TIFF **      const tifPP,
+                          int  *       const ofdP) {
+/*----------------------------------------------------------------------------
+  Create a TIFF generator that writes its output to the specified file.
+
+  If the file doesn't already exist and 'createPolicy' is MayCreate,
+  create the file; otherwise fail the program.
+
+  Fail the program if the specified file is not seekable and readable.
+
+  Return the handle of the TIFF generator as *tifPP.  Also return the
+  file descriptor for the output file as *ofdP.
+-----------------------------------------------------------------------------*/
+    int fd;
+
+    if (createPolicy == MUST_EXIST)
+        fd = open(outputFileName, O_RDWR);
     else
-        option = "w";
+        fd = open(outputFileName, (O_RDWR | O_CREAT), 00644);
+
+    if (fd == -1) {
+        if (errno == ENOENT) /* Possible only if MustExist */
+            pm_error ("Cannot open file : '%s'.  File does not exist.",
+                      outputFileName);
+        else
+            pm_error ("Cannot open file : '%s'.  open() failed with "
+                      "errno %d (%s).  ",
+                      outputFileName, errno, strerror(errno));
+    }
 
-    *tifPP = TIFFFdOpen(ofd, outFileName, option);
+    if (!fileIsSeekable(fd, outputFileName))
+        pm_error("Output file (%s) is not seekable.  "
+                 "lseek() returned errno %d (%s).  "
+                 "The TIFF library can write only to "
+                 "a seekable file.",
+                 outputFileName, errno, strerror(errno));
+
+    *tifPP = TIFFFdOpen(fd, outputFileName, "a");
     if (*tifPP == NULL)
-        pm_error("error opening standard output as TIFF file.  "
+        pm_error("error opening file %s as TIFF file.  "
+                 "TIFFFdOpen() failed.", outputFileName);
+
+    *ofdP = fd;
+}
+
+
+
+static void
+createTiffGeneratorTmpfile(TIFF ** const tifPP,
+                            int  * const ofdP) {
+/*----------------------------------------------------------------------------
+  Create a TIFF generator that writes its output to an unnnamed temporary file
+  we create.
+
+  Return the handle of the TIFF generator as *tifPP.  Also return the file
+  descriptor for the temporary file as *ofdP.
+
+  The TIFF generator has a file name attribute, but it is just for messages;
+  it is not the name of a file.  We use "Internal Temporary File".
+-----------------------------------------------------------------------------*/
+    int fd;
+
+    fd = pm_tmpfile_fd();
+
+    *tifPP = TIFFFdOpen(fd, "Internal Temporary File", "w");
+
+    if (*tifPP == NULL)
+        pm_error("error opening temporary file as TIFF file.  "
                  "TIFFFdOpen() failed.");
+
+    *ofdP = fd;
+}
+
+
+
+static void
+copyBufferToStdout(int const tmpfileFd) {
+
+    FILE * tmpfileP;
+
+    tmpfileP = fdopen(tmpfileFd, "rb");
+
+    fseek(tmpfileP, 0, SEEK_SET);
+
+    while (!feof(tmpfileP) && !ferror(tmpfileP) && !ferror(stdout)) {
+        char buffer[4096];
+        size_t bytesReadCt;
+
+        bytesReadCt = fread(buffer, 1, sizeof(buffer), tmpfileP);
+
+        if (ferror(tmpfileP))
+            pm_error("Error reading from temporary file.  "
+                     "Incomplete output.  "
+                     "Errno = %s (%d)", strerror(errno), errno);
+        else
+            fwrite(buffer, 1, bytesReadCt, stdout);
+    }
+
+    fclose(tmpfileP);
 }
 
 
 
 static void
-destroyTiffGenerator(TIFF * const tifP) {
+destroyTiffGenerator(WriteMethod const writeMethod,
+                     TIFF *      const tifP,
+                     int         const ofd) {
 
     TIFFFlushData(tifP);
+
+    if (writeMethod == TMPFILE)
+        copyBufferToStdout(ofd);
+
     TIFFClose(tifP);
 }
 
@@ -825,11 +991,11 @@ createTiffColorMap(struct pam *       const pamP,
     unsigned short ** tiffColorMap;
     unsigned int plane;
     unsigned int i;
-    
+
     MALLOCARRAY_NOFAIL(tiffColorMap, pamP->depth);
     for (plane = 0; plane < pamP->depth; ++plane)
         MALLOCARRAY_NOFAIL(tiffColorMap[plane], colorMapSize);
-    
+
     for (i = 0; i < colorMapSize; ++i) {
         unsigned int plane;
         for (plane = 0; plane < pamP->depth; ++plane) {
@@ -842,7 +1008,7 @@ createTiffColorMap(struct pam *       const pamP,
     }
     *tiffColorMapP = tiffColorMap;
 }
-        
+
 
 
 static void
@@ -867,7 +1033,7 @@ setTagListFields(const struct optNameValue * const taglist,
 
     for (i = 0; taglist[i].name; ++i) {
         const tagDefinition * const tagDefP = tagDefFind(taglist[i].name);
-        
+
         if (tagDefP->put)
             tagDefP->put(tifP, tagDefP->tagnum, taglist[i].value,
                          tagDefP->choices);
@@ -878,7 +1044,7 @@ setTagListFields(const struct optNameValue * const taglist,
 
 static void
 setTiffFields(TIFF *              const tifP,
-              struct cmdlineInfo  const cmdline,
+              CmdlineInfo         const cmdline,
               struct pam *        const pamP,
               unsigned short      const bitspersample,
               unsigned short      const photometric,
@@ -940,7 +1106,7 @@ setTiffFields(TIFF *              const tifP,
 
     TIFFSetField(tifP, TIFFTAG_DOCUMENTNAME,     inputFileDescription);
     TIFFSetField(tifP, TIFFTAG_IMAGEDESCRIPTION, "converted PNM file");
- 
+
     /* Some of taglist[] overrides defaults we set above.  But taglist[]
        is defined not to specify any tag types that are not purely user
        choice.
@@ -951,10 +1117,10 @@ setTiffFields(TIFF *              const tifP,
 
 
 static void
-convertImage(FILE *             const ifP,
-             TIFF *             const tifP,
-             const char *       const inputFileDescription,
-             struct cmdlineInfo const cmdline) {
+convertImage(FILE *       const ifP,
+             TIFF *       const tifP,
+             const char * const inputFileDescription,
+             CmdlineInfo  const cmdline) {
 
     tupletable chv;
     tuplehash cht;
@@ -966,7 +1132,7 @@ convertImage(FILE *             const ifP,
     unsigned short samplesperpixel;
     unsigned short bitspersample;
     unsigned short tiff_maxval;
-    /* This is the maxval of the samples in the tiff file.  It is 
+    /* This is the maxval of the samples in the tiff file.  It is
        determined solely by the bits per sample ('bitspersample').
        */
     int bytesperrow;
@@ -979,11 +1145,11 @@ convertImage(FILE *             const ifP,
     analyzeColors(&pam, cmdline, MAXCOLORS, &chv, &colors, &grayscale);
 
     /* Go back to beginning of raster */
-    pm_seek2(ifP, &rasterPos, sizeof(rasterPos));  
+    pm_seek2(ifP, &rasterPos, sizeof(rasterPos));
 
     /* Figure out TIFF parameters. */
 
-    computeRasterParm(&pam, chv, colors, grayscale, 
+    computeRasterParm(&pam, chv, colors, grayscale,
                       cmdline.compression,
                       cmdline.minisblack, cmdline.miniswhite,
                       cmdline.indexsizeAllowed,
@@ -1008,7 +1174,7 @@ convertImage(FILE *             const ifP,
                   cmdline.taglist);
 
     writeScanLines(&pam, tifP, cht,
-                   tiff_maxval, bitspersample, photometric, bytesperrow, 
+                   tiff_maxval, bitspersample, photometric, bytesperrow,
                    cmdline.fillorder);
 
     if (tiffColorMap)
@@ -1017,63 +1183,41 @@ convertImage(FILE *             const ifP,
 
 
 
-static void
-validateReadableStdout(void) {
-/*----------------------------------------------------------------------------
-  We validate that Standard Output is readable and fail the program if
-  it isn't.
-
-  This is useful because there are situations in which the TIFF library
-  must read the output file and if it can't, it fails with an unhelpful
-  error message about a file I/O error.  We, on the other hand, produce
-  a helpful error message.
------------------------------------------------------------------------------*/
-#if !MSVCRT
-
-    int flags;
-
-    flags = fcntl(STDOUT_FILENO, F_GETFL);
-
-    if (flags < 0) {
-        /* We couldn't get the flags.  So just assume the file's OK */
-    } else {
-        if ((flags & O_RDONLY) || (flags & O_RDWR)) {
-            /* File is readable.  All is well. */
-        } else
-            pm_error("Standard Output is not opened for reading.  "
-                     "In order to create a multi-image TIFF stream, "
-                     "Standard Output must be both readable and writable.");
-    }
-#endif
-}
 
 
 
 int
-main(int argc, char *argv[]) {
-    struct cmdlineInfo cmdline;
+main(int argc, const char *argv[]) {
+    CmdlineInfo cmdline;
     const char * inputFileDescription;
-    FILE* ifP;
-    TIFF* tifP;
+    FILE * ifP;
+    TIFF * tifP;
+    int ofd;
     int eof;
     unsigned int imageSeq;
-
-    pnm_init(&argc, argv);
-
-    parseCommandLine(argc, argv, &cmdline);
     
-    ifP = pm_openr_seekable(cmdline.input_filespec);
+    pm_proginit(&argc, argv);
 
-    if (streq(cmdline.input_filespec, "-"))
-        inputFileDescription = "Standard Input";
-    else 
-        inputFileDescription = cmdline.input_filespec;
+    parseCommandLine(argc, argv, &cmdline);
 
-    if (cmdline.append)
-        validateReadableStdout();
+    ifP = pm_openr_seekable(cmdline.inputFileName);
 
-    createTiffGenerator(STDOUT_FILENO, "Standard Output", cmdline.append,
-                        &tifP);
+    if (streq(cmdline.inputFileName, "-"))
+        inputFileDescription = "Standard Input";
+    else
+        inputFileDescription = cmdline.inputFileName;
+
+    switch (cmdline.writeMethod) {
+    case DIRECT_APPEND:
+        createTiffGeneratorDirect(cmdline.output, MUST_EXIST,  &tifP, &ofd);
+        break;
+    case DIRECT_CREATE:
+        createTiffGeneratorDirect(cmdline.output, MAY_CREATE,  &tifP, &ofd);
+        break;
+    case TMPFILE:
+        createTiffGeneratorTmpfile(&tifP, &ofd);
+        break;
+    }
 
     eof = FALSE;  /* initial assumption */
     imageSeq = 0;
@@ -1081,17 +1225,17 @@ main(int argc, char *argv[]) {
     while (!eof) {
         bool success;
 
-        if (cmdline.verbose)
-            pm_message("Converting Image %u", imageSeq);
-
         pnm_nextimage(ifP, &eof);
 
         if (!eof) {
             if (imageSeq > 0)
-                validateReadableStdout();
+                validateReadableOutputFile(ofd);
+
+            if (cmdline.verbose)
+                pm_message("Converting Image %u", imageSeq);
 
             convertImage(ifP, tifP, inputFileDescription, cmdline);
-            
+
             success = TIFFWriteDirectory(tifP);
             if (!success)
                 pm_error("Unable to write TIFF image %u to file.  "
@@ -1100,8 +1244,10 @@ main(int argc, char *argv[]) {
         }
     }
 
-    destroyTiffGenerator(tifP);
+    destroyTiffGenerator(cmdline.writeMethod, tifP, ofd);
     pm_close(ifP);
 
     return 0;
 }
+
+
diff --git a/converter/other/pnmtopalm/Makefile b/converter/other/pnmtopalm/Makefile
index 65790002..edc7da64 100644
--- a/converter/other/pnmtopalm/Makefile
+++ b/converter/other/pnmtopalm/Makefile
@@ -8,8 +8,10 @@ VPATH=.:$(SRCDIR)/$(SUBDIR)
 include $(BUILDDIR)/config.mk
 
 BINARIES = palmtopnm pnmtopalm
+PORTBINARIES = $(BINARIES) gen_palm_colormap
 SCRIPTS =
-OBJECTS = $(BINARIES:%=%.o) palmcolormap.o
+ADDL_OBJECTS = palmcolormap.o
+OBJECTS = $(BINARIES:%=%.o) $(ADDL_OBJECTS) gen_palm_colormap.o
 MERGE_OBJECTS = $(BINARIES:%=%.o2) palmcolormap.o
 MERGEBINARIES = $(BINARIES)
 DATAFILES = palmcolor8.map palmgray1.map palmgray2.map palmgray4.map
@@ -18,17 +20,7 @@ all: $(BINARIES)
 
 include $(SRCDIR)/common.mk
 
-LIBOPTS = $(shell $(LIBOPT) $(NETPBMLIB))
-
-$(BINARIES): %: %.o palmcolormap.o $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ $< palmcolormap.o $(LIBOPTS) \
-	  $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD)
-
-gen_palm_colormap : % : %.c palmcolormap.o
-	$(CC) -I importinc $(CFLAGS_ALL) -o $@ \
-	  $< palmcolormap.o \
-	  $(LIBOPTS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(LADD)
-
+$(BINARIES): $(ADDL_OBJECTS)
 
 clean: cleanspecial
 .PHONY: cleanspecial
diff --git a/converter/other/pnmtopalm/gen_palm_colormap.c b/converter/other/pnmtopalm/gen_palm_colormap.c
index c7172c6b..0f3f8a5f 100644
--- a/converter/other/pnmtopalm/gen_palm_colormap.c
+++ b/converter/other/pnmtopalm/gen_palm_colormap.c
@@ -3,8 +3,8 @@
  * Based on an earlier version by Bill Janssen  <bill@janssen.org>
  */
 
-#include "ppm.h"
-#include "pm_c_util.h"
+#include "netpbm/ppm.h"
+#include "netpbm/pm_c_util.h"
 
 #include "palm.h"
 
diff --git a/converter/other/pnmtosgi.c b/converter/other/pnmtosgi.c
index 169125b3..a8df5328 100644
--- a/converter/other/pnmtosgi.c
+++ b/converter/other/pnmtosgi.c
@@ -31,17 +31,6 @@ typedef struct {
     long        length;
 } ScanLine;
 
-/* prototypes */
-static void put_big_short ARGS((short s));
-static void put_big_long ARGS((long l));
-#define put_byte(b)     (void)(putc((unsigned char)(b), stdout))
-static void put_short_as_byte ARGS((short s));
-static void write_table  ARGS((long *table, int tabsize));
-static void write_channels ARGS((int cols, int rows, int channels, void (*put) ARGS((short)) ));
-static long * build_channels ARGS((FILE *ifp, int cols, int rows, xelval maxval, int format, int bpc, int channels));
-static ScanElem *compress ARGS((ScanElem *temp, int row, int rows, int cols, int chan_no, long *table, int bpc));
-static int rle_compress ARGS((ScanElem *inbuf, int cols));
-
 #define WORSTCOMPR(x)   (2*(x) + 2)
 
 
@@ -55,301 +44,348 @@ static ScanElem * rletemp;
 static xel * pnmrow;
 
 
-static void
-write_header(int const cols, 
-             int const rows, 
-             xelval const maxval, 
-             int const bpc, 
-             int const dimensions, 
-             int const channels, 
-             const char * const imagename)
-{
-    int i;
-
-#ifdef DEBUG
-    pm_message("writing header");
-#endif
-
-    put_big_short(SGI_MAGIC);
-    put_byte(storage);
-    put_byte((char)bpc);
-    put_big_short(dimensions);
-    put_big_short(cols);
-    put_big_short(rows);
-    put_big_short(channels);
-    put_big_long(0);                /* PIXMIN */
-    put_big_long(maxval);           /* PIXMAX */
-    for( i = 0; i < 4; i++ )
-        put_byte(0);
-    for( i = 0; i < 79 && imagename[i] != '\0'; i++ )
-        put_byte(imagename[i]);
-    for(; i < 80; i++ )
-        put_byte(0);
-    put_big_long(CMAP_NORMAL);
-    for( i = 0; i < 404; i++ )
-        put_byte(0);
-}
 
+#define putByte(b) (void)(putc((unsigned char)(b), stdout))
 
 
-int
-main(int argc,char * argv[])
-{
-    FILE *ifp;
-    int argn;
-    const char * const usage = "[-verbatim|-rle] [-imagename <name>] [pnmfile]";
-    int cols, rows, format;
-    xelval maxval, newmaxval;
-    const char *imagename = "no name";
-    int bpc, dimensions, channels;
-    long *table = NULL;
+static void
+putBigShort(short const s) {
 
-    pnm_init(&argc, argv);
+    if (pm_writebigshort(stdout, s ) == -1)
+        pm_error( "write error" );
+}
 
-    argn = 1;
-    while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
-        if( pm_keymatch(argv[argn], "-verbatim", 2) )
-            storage = STORAGE_VERBATIM;
-        else
-        if( pm_keymatch(argv[argn], "-rle", 2) )
-            storage = STORAGE_RLE;
-        else
-        if( pm_keymatch(argv[argn], "-imagename", 2) ) {
-            if( ++argn >= argc )
-                pm_usage(usage);
-            imagename = argv[argn];
-        }
-        else
-            pm_usage(usage);
-        ++argn;
-    }
 
-    if( argn < argc ) {
-        ifp = pm_openr( argv[argn] );
-        argn++;
-    }
-    else
-        ifp = stdin;
 
-    if( argn != argc )
-        pm_usage(usage);
+static void
+putBigLong(long const l) {
 
-    pnm_readpnminit(ifp, &cols, &rows, &maxval, &format);
-    if( rows>INT16MAX || cols>INT16MAX )
-      pm_error ("Input image is too large.");
+    if (pm_writebiglong( stdout, l ) == -1)
+        pm_error( "write error" );
+}
 
-    pnmrow = pnm_allocrow(cols);
 
-    switch( PNM_FORMAT_TYPE(format) ) {
-        case PBM_TYPE:
-            newmaxval = PGM_MAXMAXVAL;
-            pm_message("promoting PBM to PGM");
-        case PGM_TYPE:
-            newmaxval = maxval;
-            dimensions = 2; channels = 1;
-            break;
-        case PPM_TYPE:
-            newmaxval = maxval;
-            dimensions = 3; channels = 3;
-            break;
-        default:
-            pm_error("can\'t happen");
-    }
-    if( newmaxval <= MAXVAL_BYTE )
-        bpc = 1;
-    else if( newmaxval <= MAXVAL_WORD )
-        bpc = 2;
-    else
-        pm_error("maxval too large - try using \"pnmdepth %d\"", MAXVAL_WORD);
 
-    table = build_channels(ifp, cols, rows, newmaxval, format, bpc, channels);
-    pnm_freerow(pnmrow);
-    pm_close(ifp);
-
-    write_header(cols, rows, newmaxval, bpc, dimensions, channels, imagename);
-    if( table )
-        write_table(table, rows * channels);
-    if( bpc == 1 )
-        write_channels(cols, rows, channels, put_short_as_byte);
-    else
-        write_channels(cols, rows, channels, put_big_short);
+static void
+putShortAsByte(short const s) {
 
-    exit(0);
+    putByte((unsigned char)s);
 }
 
 
+
 static void
-write_table(long * table, int const tabsize)
-{
-    int i;
-    long offset;
+writeTable(long *       const table,
+           unsigned int const tabsize) {
 
-#ifdef DEBUG
-    pm_message("writing table");
-#endif
+    unsigned int i;
+    unsigned long offset;
 
     offset = HeaderSize + tabsize * 8;
-    for( i = 0; i < tabsize; i++ ) {
-        put_big_long(offset);
+
+    for (i = 0; i < tabsize; ++i) {
+        putBigLong(offset);
         offset += table[i];
     }
-    for( i = 0; i < tabsize; i++ )
-        put_big_long(table[i]);
+    for (i = 0; i < tabsize; ++i)
+        putBigLong(table[i]);
 }
 
 
+
 static void
-write_channels(int const cols,int const rows, int const channels,
-               void (*put) (short))
-{
-    int i, row, col;
-
-#ifdef DEBUG
-    pm_message("writing image data");
-#endif
-
-    for( i = 0; i < channels; i++ ) {
-        for( row = 0; row < rows; row++ ) {
-            for( col = 0; col < channel[i][row].length; col++ ) {
+writeChannels(unsigned int const cols,
+              unsigned int const rows,
+              unsigned int const channels,
+              void (*put) (short)) {
+
+    unsigned int i;
+
+    for (i = 0; i < channels; ++i) {
+        unsigned int row;
+        for (row = 0; row < rows; ++row) {
+            unsigned int col;
+            for (col = 0; col < channel[i][row].length; ++col) {
                 (*put)(channel[i][row].data[col]);
             }
         }
     }
 }
 
-static void
-put_big_short(short const s)
-{
-    if ( pm_writebigshort( stdout, s ) == -1 )
-        pm_error( "write error" );
-}
 
 
-static void
-put_big_long(long const l)
-{
-    if ( pm_writebiglong( stdout, l ) == -1 )
-        pm_error( "write error" );
+static int
+rleCompress(ScanElem *   const inbuf,
+            unsigned int const size) {
+
+    /* slightly modified RLE algorithm from ppmtoilbm.c written by Robert
+       A. Knop (rknop@mop.caltech.edu)
+    */
+
+    int in, out, hold, count;
+    ScanElem *outbuf = rletemp;
+
+    in = out = 0;
+    while (in < size) {
+        if ((in < size-1) && (inbuf[in] == inbuf[in+1])) {
+            /*Begin replicate run*/
+            for (count = 0, hold = in; in < size &&
+                     inbuf[in] == inbuf[hold] && count < 127;
+                 ++in, ++count)
+                ;
+            outbuf[out++] = (ScanElem)(count);
+            outbuf[out++] = inbuf[hold];
+        } else {
+            /*Do a literal run*/
+            hold = out;
+            ++out;
+            count = 0;
+            while (((in >= size-2) && (in < size))
+                   || ((in < size-2) && ((inbuf[in] != inbuf[in+1])
+                                         || (inbuf[in] != inbuf[in+2])))) {
+                outbuf[out++] = inbuf[in++];
+                if (++count >= 127)
+                    break;
+            }
+            outbuf[hold] = (ScanElem)(count | 0x80);
+        }
+    }
+    outbuf[out++] = (ScanElem)0;     /* terminator */
+
+    return out;
 }
 
 
-static void
-put_short_as_byte(short const s)
-{
-    put_byte((unsigned char)s);
+
+static ScanElem *
+compress(ScanElem *   const tempArg,
+         unsigned int const row,
+         unsigned int const rows,
+         unsigned int const cols,
+         unsigned int const chanNum,
+         long *       const table,
+         unsigned int const bpc) {
+
+    ScanElem * retval;
+
+    switch (storage) {
+    case STORAGE_VERBATIM:
+        channel[chanNum][row].length = cols;
+        channel[chanNum][row].data = tempArg;
+        MALLOCARRAY_NOFAIL(retval, cols);
+        break;
+    case STORAGE_RLE: {
+        unsigned int const tabrow = chanNum * rows + row;
+        unsigned int const len = rleCompress(tempArg, cols);
+            /* writes result into rletemp */
+        unsigned int i;
+        ScanElem * p;
+        
+        channel[chanNum][row].length = len;
+        MALLOCARRAY(p, len);
+        channel[chanNum][row].data = p;
+        for (i = 0; i < len; ++i)
+            p[i] = rletemp[i];
+        table[tabrow] = len * bpc;
+        retval = tempArg;
+    } break;
+    default:
+        pm_error("unknown storage type - can't happen");
+    }
+    return retval;
 }
 
 
+
 static long *
-build_channels(FILE * const ifp, int const cols, int const rows,
-               xelval const maxval, int const format,
-               int const bpc, int const channels)
-{
-    int i, row, col, sgirow;
-    long *table = NULL;
-    ScanElem *temp;
-
-#ifdef DEBUG
-    pm_message("building channels");
-#endif
-
-    if( storage != STORAGE_VERBATIM ) {
+buildChannels(FILE *       const ifP,
+              unsigned int const cols,
+              unsigned int const rows,
+              xelval       const maxval,
+              int          const format,
+              unsigned int const bpc,
+              unsigned int const channels) {
+
+    unsigned int row;
+    unsigned int sgirow;
+    long * table;
+    ScanElem * temp;
+
+    if (storage != STORAGE_VERBATIM) {
         MALLOCARRAY_NOFAIL(table, channels * rows);
         MALLOCARRAY_NOFAIL(rletemp, WORSTCOMPR(cols));
-    }
+    } else
+        table = NULL;
+
     MALLOCARRAY_NOFAIL(temp, cols);
 
-    for( i = 0; i < channels; i++ )
-        MALLOCARRAY_NOFAIL(channel[i], rows);
+    {
+        unsigned int i;
+        for (i = 0; i < channels; ++i)
+            MALLOCARRAY_NOFAIL(channel[i], rows);
+    }
 
-    for( row = 0, sgirow = rows-1; row < rows; row++, sgirow-- ) {
-        pnm_readpnmrow(ifp, pnmrow, cols, maxval, format);
-        if( channels == 1 ) {
-            for( col = 0; col < cols; col++ )
+    for (row = 0, sgirow = rows-1; row < rows; ++row, --sgirow) {
+        pnm_readpnmrow(ifP, pnmrow, cols, maxval, format);
+        if (channels == 1) {
+            unsigned int col;
+            for (col = 0; col < cols; ++col)
                 temp[col] = (ScanElem)PNM_GET1(pnmrow[col]);
             temp = compress(temp, sgirow, rows, cols, 0, table, bpc);
-        }
-        else {
-            for( col = 0; col < cols; col++ )
+        } else {
+            unsigned int col;
+            for (col = 0; col < cols; ++col)
                 temp[col] = (ScanElem)PPM_GETR(pnmrow[col]);
             temp = compress(temp, sgirow, rows, cols, 0, table, bpc);
-            for( col = 0; col < cols; col++ )
+            for (col = 0; col < cols; ++col)
                 temp[col] = (ScanElem)PPM_GETG(pnmrow[col]);
             temp = compress(temp, sgirow, rows, cols, 1, table, bpc);
-            for( col = 0; col < cols; col++ )
+            for (col = 0; col < cols; ++col)
                 temp[col] = (ScanElem)PPM_GETB(pnmrow[col]);
             temp = compress(temp, sgirow, rows, cols, 2, table, bpc);
         }
     }
 
     free(temp);
-    if( table )
+    if (table)
         free(rletemp);
     return table;
 }
 
 
-static ScanElem *
-compress(ScanElem * temp,
-         int const row,  int const rows,
-         int const cols, int const chan_no,
-         long * table, int const bpc)
-{
-    int len, i, tabrow;
-    ScanElem *p;
-
-    switch( storage ) {
-        case STORAGE_VERBATIM:
-            channel[chan_no][row].length = cols;
-            channel[chan_no][row].data = temp;
-            MALLOCARRAY_NOFAIL(temp, cols);
+
+static void
+writeHeader(unsigned int const cols, 
+            unsigned int const rows, 
+            xelval       const maxval, 
+            unsigned int const bpc, 
+            unsigned int const dimensions, 
+            unsigned int const channels, 
+            const char * const imagename) {
+
+    unsigned int i;
+
+    putBigShort(SGI_MAGIC);
+    putByte(storage);
+    putByte((char)bpc);
+    putBigShort(dimensions);
+    putBigShort(cols);
+    putBigShort(rows);
+    putBigShort(channels);
+    putBigLong(0);                /* PIXMIN */
+    putBigLong(maxval);           /* PIXMAX */
+
+    for(i = 0; i < 4; ++i)
+        putByte(0);
+
+    for (i = 0; i < 79 && imagename[i] != '\0'; ++i)
+        putByte(imagename[i]);
+
+    for(; i < 80; ++i)
+        putByte(0);
+
+    putBigLong(CMAP_NORMAL);
+
+    for (i = 0; i < 404; ++i)
+        putByte(0);
+}
+
+
+
+int
+main(int argc,char * argv[]) {
+
+    FILE * ifP;
+    int argn;
+    const char * const usage = "[-verbatim|-rle] [-imagename <name>] [pnmfile]";
+    int cols, rows;
+    int format;
+    xelval maxval, newmaxval;
+    const char * imagename;
+    unsigned int bpc;
+    unsigned int dimensions;
+    unsigned int channels;
+    long * table;
+
+    pnm_init(&argc, argv);
+
+    imagename = "no name";  /* default value */
+    argn = 1;
+    while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
+        if( pm_keymatch(argv[argn], "-verbatim", 2) )
+            storage = STORAGE_VERBATIM;
+        else
+        if( pm_keymatch(argv[argn], "-rle", 2) )
+            storage = STORAGE_RLE;
+        else
+        if( pm_keymatch(argv[argn], "-imagename", 2) ) {
+            if( ++argn >= argc )
+                pm_usage(usage);
+            imagename = argv[argn];
+        }
+        else
+            pm_usage(usage);
+        ++argn;
+    }
+
+    if( argn < argc ) {
+        ifP = pm_openr( argv[argn] );
+        argn++;
+    }
+    else
+        ifP = stdin;
+
+    if( argn != argc )
+        pm_usage(usage);
+
+    pnm_readpnminit(ifP, &cols, &rows, &maxval, &format);
+
+    if (rows > INT16MAX || cols > INT16MAX)
+        pm_error ("Input image is too large.");
+
+    pnmrow = pnm_allocrow(cols);
+    
+    switch (PNM_FORMAT_TYPE(format)) {
+        case PBM_TYPE:
+            pm_message("promoting PBM to PGM");
+            newmaxval = PGM_MAXMAXVAL;
+        case PGM_TYPE:
+            newmaxval = maxval;
+            dimensions = 2;
+            channels = 1;
             break;
-        case STORAGE_RLE:
-            tabrow = chan_no * rows + row;
-            len = rle_compress(temp, cols);    /* writes result into rletemp */
-            channel[chan_no][row].length = len;
-            MALLOCARRAY(p, len);
-            channel[chan_no][row].data = p;
-            for( i = 0; i < len; i++, p++ )
-                *p = rletemp[i];
-            table[tabrow] = len * bpc;
+        case PPM_TYPE:
+            newmaxval = maxval;
+            dimensions = 3;
+            channels = 3;
             break;
         default:
-            pm_error("unknown storage type - can\'t happen");
+            pm_error("can\'t happen");
     }
-    return temp;
-}
+    if (newmaxval <= MAXVAL_BYTE)
+        bpc = 1;
+    else if (newmaxval <= MAXVAL_WORD)
+        bpc = 2;
+    else
+        pm_error("maxval too large - try using \"pnmdepth %u\"", MAXVAL_WORD);
 
+    table = buildChannels(ifP, cols, rows, newmaxval, format, bpc, channels);
 
-/*
-slightly modified RLE algorithm from ppmtoilbm.c
-written by Robert A. Knop (rknop@mop.caltech.edu)
-*/
-static int
-rle_compress(ScanElem * const inbuf, int const size)
-{
-    int in, out, hold, count;
-    ScanElem *outbuf = rletemp;
+    pnm_freerow(pnmrow);
 
-    in=out=0;
-    while( in<size ) {
-        if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) {     /*Begin replicate run*/
-            for( count=0,hold=in; in<size && inbuf[in]==inbuf[hold] && count<127; in++,count++)
-                ;
-            outbuf[out++]=(ScanElem)(count);
-            outbuf[out++]=inbuf[hold];
-        }
-        else {  /*Do a literal run*/
-            hold=out; out++; count=0;
-            while( ((in>=size-2)&&(in<size)) || ((in<size-2) && ((inbuf[in]!=inbuf[in+1])||(inbuf[in]!=inbuf[in+2]))) ) {
-                outbuf[out++]=inbuf[in++];
-                if( ++count>=127 )
-                    break;
-            }
-            outbuf[hold]=(ScanElem)(count | 0x80);
-        }
-    }
-    outbuf[out++] = (ScanElem)0;     /* terminator */
-    return(out);
+    pm_close(ifP);
+
+    writeHeader(cols, rows, newmaxval, bpc, dimensions, channels, imagename);
+
+    if (table)
+        writeTable(table, rows * channels);
+
+    if (bpc == 1)
+        writeChannels(cols, rows, channels, putShortAsByte);
+    else
+        writeChannels(cols, rows, channels, putBigShort);
+
+    return 0;
 }
 
+
diff --git a/converter/other/sgi.h b/converter/other/sgi.h
index 3700d356..2f57f52d 100644
--- a/converter/other/sgi.h
+++ b/converter/other/sgi.h
@@ -5,7 +5,7 @@
 
 typedef struct {
     short           magic;
-    char            storage;
+    unsigned char   storage;
     char            bpc;            /* pixel size: 1 = bytes, 2 = shorts */
     unsigned short  dimension;      /* 1 = single row, 2 = B/W, 3 = RGB */
     unsigned short  xsize,          /* width in pixels */
@@ -25,9 +25,9 @@ typedef struct {
 #define STORAGE_RLE         1
 
 #define CMAP_NORMAL         0
-#define CMAP_DITHERED       1   /* not supported */
-#define CMAP_SCREEN         2   /* not supported */
-#define CMAP_COLORMAP       3   /* not supported */
+#define CMAP_DITHERED       1   /* can't handle this */
+#define CMAP_SCREEN         2   /* can't handle this */
+#define CMAP_COLORMAP       3   /* can't handle this */
 
 #endif
 
diff --git a/converter/other/sgitopnm.c b/converter/other/sgitopnm.c
index ea2daef3..008d5376 100644
--- a/converter/other/sgitopnm.c
+++ b/converter/other/sgitopnm.c
@@ -5,6 +5,11 @@
 ** Based on the SGI image description v0.9 by Paul Haeberli (paul@sgi.comp)
 ** Available via ftp from sgi.com:graphics/SGIIMAGESPEC
 **
+** The definitive document describing the SGI image file format,
+** SGI Image File Format Version 1.00 is available from
+** ftp://ftp.sgi.com/graphics/grafica/sgiimage.html
+**
+**
 ** Permission to use, copy, modify, and distribute this software and its
 ** documentation for any purpose and without fee is hereby granted, provided
 ** that the above copyright notice appear in all copies and that both that
@@ -12,12 +17,9 @@
 ** documentation.  This software is provided "as is" without express or
 ** implied warranty.
 **
-** 29Jan94: first version
-** 08Feb94: minor bugfix
-** 29Jul00: added -channel option (smar@reptiles.org)
-** 19Oct10: added checks for artihmetic overflows
-**          fixed problem with -channel on verbatim sgi images (afu)
 */
+
+
 #include <unistd.h>
 #include <limits.h>
 #include "pm_c_util.h"
@@ -28,12 +30,12 @@
 
 
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *  inputFileName;  /* '-' if stdin */
-    unsigned int  verbose;
+    const char * inputFileName;  /* '-' if stdin */
+    unsigned int verbose;
     unsigned int channelSpec;
     unsigned int channel;
 };
@@ -42,10 +44,10 @@ struct cmdlineInfo {
 
 static void
 parseCommandLine(int argc, const char ** argv,
-                 struct cmdlineInfo * const cmdlineP) {
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -53,7 +55,7 @@ parseCommandLine(int argc, const char ** argv,
    Note that the strings we return are stored in the storage that
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
-    optEntry *option_def;
+    optEntry * option_def;
         /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
@@ -68,7 +70,7 @@ parseCommandLine(int argc, const char ** argv,
             &cmdlineP->channelSpec,            0);
     OPTENT3(0, "verbose",             OPT_FLAG,      NULL,
             &cmdlineP->verbose,       0);
-    OPTENT3(0, "noverbose",             OPT_FLAG,      NULL,
+    OPTENT3(0, "noverbose",           OPT_FLAG,      NULL,
             NULL,       0);  /* backward compatibility */
 
     opt.opt_table = option_def;
@@ -78,6 +80,8 @@ parseCommandLine(int argc, const char ** argv,
     pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
+    free(option_def);
+
     if (argc-1 < 1)
         cmdlineP->inputFileName = "-";
     else if (argc-1 == 1)
@@ -165,9 +169,9 @@ getByteAsShort(FILE * const ifP) {
 
 
 static const char *
-compressionName(char const compr) {
+compressionName(unsigned char const storageCode) {
 
-    switch (compr) {
+    switch (storageCode) {
     case STORAGE_VERBATIM:
         return "none";
     case STORAGE_RLE:
@@ -214,7 +218,7 @@ readHeader(FILE *       const ifP,
     headP->pixmin    = getBigLong(ifP);
     headP->pixmax    = getBigLong(ifP);
     if (headP->pixmin >= headP->pixmax)
-        pm_error("Invalid sgi image header: pixmin larger than pixmax");   
+        pm_error("Invalid sgi image header: pixmin larger than pixmax");
     readBytes(ifP, 4, headP->dummy1);
     readBytes(ifP, 80, headP->name);
     headP->colormap  = getBigLong(ifP);
@@ -243,26 +247,32 @@ readHeader(FILE *       const ifP,
             headP->dimension = 2;
             break;
         case 2:
-            pm_error("don't know how to interpret 2-channel image");
+            if (!outChannelSpec)
+                pm_message("2-channel image, using only first channel.  "
+                           "Extract alpha channel with -channel=1");
             break;
         case 3:
             break;
         default:
             if (!outChannelSpec)
-                pm_message("%d-channel image, using only first 3 channels",
-                           headP->zsize);
+                pm_message("%u-channel image, using only first 3 channels  "
+                           "Extract %s with -channel=%c",
+                            headP->zsize,
+                            headP->zsize==4 ?
+                                "alpha channel" : "additional channels",
+                            headP->zsize==4 ? '3' : 'N');
             break;
         }
         break;
     default:
-        pm_error("illegal dimension value %d (only 1-3 allowed)",
+        pm_error("illegal dimension value %u (only 1-3 allowed)",
                  headP->dimension);
     }
 
     if (verbose) {
-        pm_message("raster size %dx%d, %d channels",
+        pm_message("raster size %ux%u, %u channels",
                    headP->xsize, headP->ysize, headP->zsize);
-        pm_message("compression: %d = %s",
+        pm_message("compression: 0x%02x = %s",
                    headP->storage, compressionName(headP->storage));
         headP->name[79] = '\0';  /* just to be safe */
         pm_message("Image name: '%s'", headP->name);
@@ -345,7 +355,7 @@ rleDecompress(ScanElem * const srcStart,
 static ScanLine *
 readChannels(FILE *       const ifP,
              Header *     const head,
-             TabEntry *   const table, 
+             TabEntry *   const table,
              bool         const outChannelSpec,
              unsigned int const outChannel) {
 
@@ -357,11 +367,14 @@ readChannels(FILE *       const ifP,
     if (outChannelSpec) {
         maxchannel = outChannel + 1;
         MALLOCARRAY_NOFAIL(image, head->ysize);
+    } else if (head->zsize <= 2) {
+        maxchannel = 1;
+        MALLOCARRAY_NOFAIL(image, head->ysize);
     } else {
-        maxchannel = MIN(3, head->zsize);
+        maxchannel = 3;
         MALLOCARRAY_NOFAIL(image, head->ysize * maxchannel);
     }
-    if (table) 
+    if (table)
         MALLOCARRAY_NOFAIL(temp, WORSTCOMPR(head->xsize));
 
     for (channel = 0; channel < maxchannel; ++channel) {
@@ -377,16 +390,17 @@ readChannels(FILE *       const ifP,
 
             if (table) {
                 if (!outChannelSpec || channel >= outChannel) {
-                    long const offset = table[sgiIndex].start;
+                    pm_filepos const offset = (pm_filepos)
+                        table[sgiIndex].start;
                     long const length = head->bpc == 2 ?
                         table[sgiIndex].length / 2 :
                         table[sgiIndex].length;
 
                     unsigned int i;
 
-                    /* doc says length is in bytes, we are reading words */
-                    if (fseek(ifP, offset, SEEK_SET) != 0)
-                        pm_error("seek error for offset %ld", offset);
+                    /* Note: (offset < currentPosition) can happen */
+
+                    pm_seek2(ifP, &offset, sizeof(offset));
 
                     for (i = 0; i < length; ++i)
                         if (head->bpc == 1)
@@ -404,7 +418,7 @@ readChannels(FILE *       const ifP,
                     else
                         p = getBigShort(ifP);
 
-                    if (channel == outChannel || !outChannelSpec)
+                    if (!outChannelSpec || outChannel == channel)
                         image[iindex][i] = p;
                 }
             }
@@ -430,7 +444,7 @@ imageToPnm(Header   *   const head,
     int row;
     int format;
 
-    if (head->zsize == 1 || outChannelSpec) {
+    if (head->zsize <= 2 || outChannelSpec) {
         pm_message("writing PGM image");
         format = PGM_TYPE;
     } else {
@@ -459,10 +473,10 @@ imageToPnm(Header   *   const head,
 
 
 
-int 
+int
 main(int argc, const char * argv[]) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     TabEntry * table;
     ScanLine * image;
@@ -472,8 +486,8 @@ main(int argc, const char * argv[]) {
     pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
-    
-    ifP = pm_openr(cmdline.inputFileName);    
+
+    ifP = pm_openr_seekable(cmdline.inputFileName);
 
     headP = readHeader(ifP, cmdline.channelSpec, cmdline.verbose);
 
@@ -491,14 +505,14 @@ main(int argc, const char * argv[]) {
         table = readTable(ifP, headP->ysize * headP->zsize);
     else
         table = NULL;
- 
+
     image = readChannels(ifP, headP, table,
                          cmdline.channelSpec, cmdline.channel);
 
     imageToPnm(headP, image, maxval, cmdline.channelSpec, cmdline.channel);
 
     pm_close(ifP);
- 
+
     return 0;
 }
 
diff --git a/converter/other/tifftopnm.c b/converter/other/tifftopnm.c
index fcfb03f6..214c02aa 100644
--- a/converter/other/tifftopnm.c
+++ b/converter/other/tifftopnm.c
@@ -1457,7 +1457,7 @@ convertRasterInMemory(pnmOut *       const pnmOutP,
         int ok;
         ok = TIFFRGBAImageOK(tif, emsg);
         if (!ok) {
-            pm_message(emsg);
+            pm_message("%s", emsg);
             *statusP = CONV_UNABLE;
         } else {
             uint32 * raster;
@@ -1477,14 +1477,14 @@ convertRasterInMemory(pnmOut *       const pnmOutP,
                 
                 ok = TIFFRGBAImageBegin(&img, tif, stopOnErrorFalse, emsg);
                 if (!ok) {
-                    pm_message(emsg);
+                    pm_message("%s", emsg);
                     *statusP = CONV_FAILED;
                 } else {
                     int ok;
                     ok = TIFFRGBAImageGet(&img, raster, cols, rows);
                     TIFFRGBAImageEnd(&img) ;
                     if (!ok) {
-                        pm_message(emsg);
+                        pm_message("%s", emsg);
                         *statusP = CONV_FAILED;
                     } else {
                         *statusP = CONV_DONE;