From 1610a1f6aa54ad1d97926c1d8605720933059df7 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sun, 29 Jun 2014 19:18:54 +0000 Subject: Update Advanced series to Release 10.67 git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@2221 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/bmp.h | 4 +- converter/other/Makefile | 128 +- converter/other/cameratopam/Makefile | 14 +- converter/other/exif.c | 1197 +++---- converter/other/exif.h | 22 +- converter/other/fiasco/Makefile | 16 +- converter/other/fiasco/codec/ip.c | 4 +- converter/other/fiasco/codec/tiling.c | 2 +- converter/other/fiasco/codec/wfa.h | 2 +- converter/other/fiasco/display.c | 3 +- converter/other/fiasco/lib/image.c | 2 +- converter/other/fiasco/params.c | 2 +- converter/other/fiasco/pnmtofiasco.c | 2 +- converter/other/jbig/ANNOUNCE | 243 -- converter/other/jbig/Makefile | 32 +- converter/other/jbig/README | 20 + converter/other/jbig/README.Netpbm | 12 - converter/other/jbig/jbig.c | 2905 ----------------- converter/other/jbig/jbig.doc | 721 ----- converter/other/jbig/jbig.h | 267 -- converter/other/jbig/jbig_tab.c | 428 --- converter/other/jbig/jbigtopnm.c | 2 +- converter/other/jbig/libjbig/ANNOUNCE | 172 + converter/other/jbig/libjbig/COPYING | 339 ++ converter/other/jbig/libjbig/Makefile | 24 + converter/other/jbig/libjbig/include/jbig.h | 233 ++ converter/other/jbig/libjbig/include/jbig_ar.h | 53 + converter/other/jbig/libjbig/jbig.c | 3285 ++++++++++++++++++++ converter/other/jbig/libjbig/jbig.txt | 810 +++++ converter/other/jbig/libjbig/jbig_ar.c | 417 +++ converter/other/jpeg2000/Makefile | 13 +- converter/other/jpeg2000/jpeg2ktopam.c | 3 +- .../other/jpeg2000/libjasper/base/jas_image.c | 2 +- .../jpeg2000/libjasper/include/jasper/jas_image.h | 38 +- converter/other/jpeg2000/libjasper/jp2/jp2_dec.c | 4 +- converter/other/jpeg2000/libjasper/jpc/jpc_cs.c | 2 - converter/other/jpeg2000/libjasper/jpc/jpc_enc.c | 2 +- converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c | 8 +- converter/other/jpeg2000/pamtojpeg2k.c | 3 +- converter/other/jpegtopnm.c | 12 +- converter/other/pamtosvg/Makefile | 32 +- converter/other/pamtosvg/bitmap.h | 2 +- converter/other/pamtosvg/image-proc.c | 2 +- converter/other/pamtosvg/thin-image.c | 2 +- converter/other/pamtotiff.c | 452 ++- converter/other/pnmtopalm/Makefile | 16 +- converter/other/pnmtopalm/gen_palm_colormap.c | 4 +- converter/other/pnmtosgi.c | 512 +-- converter/other/sgi.h | 8 +- converter/other/sgitopnm.c | 86 +- converter/other/tifftopnm.c | 6 +- converter/pbm/cmuwmtopbm.c | 8 +- converter/pbm/pbmtoppa/Makefile | 17 +- converter/ppm/ilbm.h | 6 +- converter/ppm/ppmtompeg/Makefile | 62 +- converter/ppm/ppmtompeg/gethostname_win32.c | 2 +- 56 files changed, 6846 insertions(+), 5819 deletions(-) delete mode 100644 converter/other/jbig/ANNOUNCE create mode 100644 converter/other/jbig/README delete mode 100644 converter/other/jbig/README.Netpbm delete mode 100644 converter/other/jbig/jbig.c delete mode 100644 converter/other/jbig/jbig.doc delete mode 100644 converter/other/jbig/jbig.h delete mode 100644 converter/other/jbig/jbig_tab.c create mode 100644 converter/other/jbig/libjbig/ANNOUNCE create mode 100644 converter/other/jbig/libjbig/COPYING create mode 100644 converter/other/jbig/libjbig/Makefile create mode 100644 converter/other/jbig/libjbig/include/jbig.h create mode 100644 converter/other/jbig/libjbig/include/jbig_ar.h create mode 100644 converter/other/jbig/libjbig/jbig.c create mode 100644 converter/other/jbig/libjbig/jbig.txt create mode 100644 converter/other/jbig/libjbig/jbig_ar.c (limited to 'converter') diff --git a/converter/bmp.h b/converter/bmp.h index 6a883394..524bbf7e 100644 --- a/converter/bmp.h +++ b/converter/bmp.h @@ -105,8 +105,8 @@ BMPCompTypeName(BMPCompType const compression) { case BMPCOMP_RLE4: return "4 bit run-length coding"; case BMPCOMP_RLE8: return "8 bit run-length coding"; case BMPCOMP_BITFIELDS: return "none (bitfields)"; - case BMPCOMP_JPEG: return "JPEG (not supported)"; - case BMPCOMP_PNG: return "PNG (not supported)"; + case BMPCOMP_JPEG: return "JPEG"; + case BMPCOMP_PNG: return "PNG"; } return 0; /* Default compiler warning */ } 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= 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;aCameraMake, (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;aComments[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 +#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", - , - -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 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 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 - - - - 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 ) - - - 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: 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 b/converter/other/jbig/README new file mode 100644 index 00000000..bd7a4745 --- /dev/null +++ b/converter/other/jbig/README @@ -0,0 +1,20 @@ +The jbig tools are derived from the JBIG-KIT package by Marcus Kuhn, +by Bryan Henderson on 2000.05.11. + +The file ANNOUNCE in the 'libjbig' subdirectory 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 code in subdirectory 'libjbig' is straight from the JBIG_KIT package and +generates essentially the same libjbig.a that one gets from that package. + +The code is based on JBIG-KIT version 2.1, adapted to Netpbm by Bryan +Henderson in June 2014. + +The reason Netpbm contains a copy of the library is convenience of users. For +many people, the only reason to have a jbig library is to be able to convert +images to and from the format, which they do with Netpbm. Requiring a Netpbm +user to find and install this esoteric library is impractical. \ No newline at end of file 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 -#endif - -#include -#include - -#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 or . - -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 -#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) - - -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 - -/* - * 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/jbig/libjbig/ANNOUNCE b/converter/other/jbig/libjbig/ANNOUNCE new file mode 100644 index 00000000..15ce550d --- /dev/null +++ b/converter/other/jbig/libjbig/ANNOUNCE @@ -0,0 +1,172 @@ + +JBIG-KIT lossless image compression library +------------------------------------------- + +by Markus Kuhn + + +The latest release of JBIG-KIT can be downloaded from + + http://www.cl.cam.ac.uk/~mgk25/jbigkit/ + +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 two variants of a portable library of compression +and decompression functions with a documented interface. 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", + , + +which is commonly referred to as the "JBIG1 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, JBIG has also been developed and published by the International +Organization for Standardization (ISO) and the International +Telecommunication Union (ITU). See also + + http://www.jpeg.org/jbig/ + http://www.iso.ch/ + http://www.itu.int/ + +The JBIG compression algorithm offers the following features: + + - Close to state-of-the-art lossless compression ratio for high + resolution bi-level images. + + - About 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. + + - About 2 times better compression on typical 300 dpi documents + compared to 'gzip -9' on raw bitmaps. + + - About 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 quite sophisticated + resolution reduction algorithm which offers high 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 grayscale 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 grayscale images with up to + 6 bit per pixel, JBIG performs superior to JPEG's lossless + mode. + +JBIG-KIT can be used as free software under the GNU General Public +License. Other license arrangements more suitable for commercial +applications are available as well, please contact the author for +details. JBIG-KIT provides two portable libraries implemented in +ANSI/ISO C for encoding and decoding JBIG data streams, along with +documentation. The first library, jbig.c, implements nearly all of the +options that the JBIG standard provides, but keeps the entire +uncompressed image in memory. The second library, jbig85.c, implements +only the ITU-R T.85 subset of the standard that black/white fax +machines use (single bit per pixel, no "progressive" encoding), and +keeps only three lines of the uncompressed image in memory, making it +particularly attractive for low-memory embedded applications. + +The libraries are not intended for 8-bit or 16-bit machine +architectures (e.g., old MS-DOS C compilers). For maximum performance, +a 32-bit processor is required (64-bit systems work too, of course). +On architectures with 16-bit pointer arithmetic, the full-featured +jbig.c library can process only very small images. + +Special features of the full-featured jbig.c variant: + + - 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 thread + + - 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) + + - Suitable for fax applications, satisfies ITU-T T.85 profile + + - 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 grayscale images + + - Ready-to-use pbmtojbg and jbgtopbm converters. + +Special features of the light-weight jbig85.c variant: + + - Suitable for low-memory embedded applications + + - Implements only the JBIG1 subset defined in the ITU-T T.85 + profile (single bit plane, no differential layers) + + - Requires only three pixel rows of the uncompressed image to be + kept in memory + + - Handles all NEWLEN modes of operation required by ITU-T T.85 with + just a single pass over the data, automatically performing the + necessary lookahead after the last stripe + + - Codec buffers only a few bytes of arithmetic-codec data and outputs + resulting bytes or lines as soon as they are available. + +I will try to provide free support and maintenance for this software +for the foreseeable future, depending on my available time. + +Happy compressing ... + +Markus Kuhn + +-- +Markus Kuhn, Computer Laboratory, University of Cambridge +http://www.cl.cam.ac.uk/~mgk25/ || CB3 0FD, Great Britain diff --git a/converter/other/jbig/libjbig/COPYING b/converter/other/jbig/libjbig/COPYING new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/converter/other/jbig/libjbig/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/converter/other/jbig/libjbig/Makefile b/converter/other/jbig/libjbig/Makefile new file mode 100644 index 00000000..2e574903 --- /dev/null +++ b/converter/other/jbig/libjbig/Makefile @@ -0,0 +1,24 @@ +ifeq ($(SRCDIR)x,x) + SRCDIR = $(CURDIR)/../../../.. + BUILDDIR = $(SRCDIR) +endif +SUBDIR = converter/other/jbig/libjbig +VPATH=.:$(SRCDIR)/$(SUBDIR) + +include $(BUILDDIR)/config.mk + +LIBJBIG_OBJECTS = jbig.o jbig_ar.o + +OBJECTS = $(LIBJBIG_OBJECTS) +MERGE_OBJECTS = $(LIBJBIG_OBJECTS) + +COMP_INCLUDES = -I$(SRCDIR)/$(SUBDIR)/include + +all: libjbig.a + +include $(SRCDIR)/common.mk + +libjbig.a: $(LIBJBIG_OBJECTS) + $(AR) -rc $@ $^ + $(RANLIB) $@ + diff --git a/converter/other/jbig/libjbig/include/jbig.h b/converter/other/jbig/libjbig/include/jbig.h new file mode 100644 index 00000000..67994107 --- /dev/null +++ b/converter/other/jbig/libjbig/include/jbig.h @@ -0,0 +1,233 @@ +/* + * Header file for the portable JBIG compression library + * + * Copyright 1995-2014 -- Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ + */ + +#ifndef JBG_H +#define JBG_H + +#include +#include "jbig_ar.h" + +/* + * JBIG-KIT version number + */ + +#define JBG_VERSION "2.1" +#define JBG_VERSION_MAJOR 2 +#define JBG_VERSION_MINOR 1 + +/* + * JBIG-KIT licence agreement reference code: + * If you use JBIG-KIT under a commercial licence, please replace + * below the letters GPL with the reference code that you received + * with your licence agreement. (This code is typically a letter "A" + * followed by four decimal digits, e.g. "A1234".) + */ + +#define JBG_LICENCE "GPL" + +/* + * 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 ATMOVEs per stripe that decoder can handle + */ + +#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 + +/* encoding options that will not be indicated in the header */ + +#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. */ + +#define JBG_SDRST 0x200 /* Use SDRST instead of SDNORM. This option is + * there for anyone who needs to generate + * test data that covers the SDRST cases. */ + +/* + * Possible error code return values + */ + +#define JBG_EOK (0 << 4) +#define JBG_EOK_INTR (1 << 4) +#define JBG_EAGAIN (2 << 4) +#define JBG_ENOMEM (3 << 4) +#define JBG_EABORT (4 << 4) +#define JBG_EMARKER (5 << 4) +#define JBG_EINVAL (6 << 4) +#define JBG_EIMPL (7 << 4) +#define JBG_ENOCONT (8 << 4) + +/* + * 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) */ + unsigned long yd1; /* BIH announced height of image, use yd1 != yd to + emulate T.85-style NEWLEN height updates for tests */ + 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 */ + unsigned char *comment; /* content of comment marker segment to be added + at next opportunity (will be reset to NULL + as soon as comment has been written) */ + unsigned long comment_len; /* length of data pointed to by comment */ +}; + + +/* + * 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, + unsigned 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); +unsigned long jbg_dec_getwidth(const struct jbg_dec_state *s); +unsigned long jbg_dec_getheight(const struct jbg_dec_state *s); +unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane); +unsigned 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); +unsigned 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); +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); +int jbg_newlen(unsigned char *bie, size_t len); + +#endif /* JBG_H */ diff --git a/converter/other/jbig/libjbig/include/jbig_ar.h b/converter/other/jbig/libjbig/include/jbig_ar.h new file mode 100644 index 00000000..d58b1ae0 --- /dev/null +++ b/converter/other/jbig/libjbig/include/jbig_ar.h @@ -0,0 +1,53 @@ +/* + * Header file for the arithmetic encoder and decoder of + * the portable JBIG compression library + * + * Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/jbigkit/ + */ + +#ifndef JBG_AR_H +#define JBG_AR_H + +/* + * Status of arithmetic encoder + */ + +struct jbg_arenc_state { + unsigned char st[4096]; /* probability status for contexts, MSB = MPS */ + unsigned long c; /* register C: base of coding intervall, * + * layout as in Table 23 */ + unsigned long a; /* register A: normalized size of coding interval */ + long sc; /* number of buffered 0xff values that might still 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 that receives all PSCD bytes */ + void *file; /* parameter passed to byte_out */ +}; + +/* + * Status of arithmetic decoder + */ + +struct jbg_ardec_state { + unsigned char st[4096]; /* probability status for contexts, MSB = MPS */ + unsigned long c; /* register C: base of coding intervall, * + * layout as in Table 25 */ + unsigned long a; /* register A: normalized size of coding interval */ + unsigned char *pscd_ptr; /* pointer to next PSCD data byte */ + unsigned char *pscd_end; /* pointer to byte after PSCD */ + int ct; /* bit-shift counter, determines when next byte will be read; + * special value -1 signals that zero-padding has started */ + int startup; /* boolean flag that controls initial fill of s->c */ + int nopadding; /* boolean flag that triggers return -2 between + * reaching PSCD end and decoding the first symbol + * that might never have been encoded in the first + * place */ +}; + +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 /* JBG_AR_H */ diff --git a/converter/other/jbig/libjbig/jbig.c b/converter/other/jbig/libjbig/jbig.c new file mode 100644 index 00000000..1ff867e8 --- /dev/null +++ b/converter/other/jbig/libjbig/jbig.c @@ -0,0 +1,3285 @@ +/* + * Portable JBIG image compression library + * + * Copyright 1995-2014 -- Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ + * + * This module implements a portable standard C encoder and decoder + * using the JBIG1 lossless bi-level image compression algorithm + * specified in International Standard ISO 11544:1993 and + * ITU-T Recommendation T.82. See the file jbig.txt 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. + */ + +#ifdef DEBUG +#include +#else +#define NDEBUG +#endif + +#include +#include +#include + +#include "jbig.h" + +#define MX_MAX 127 + /* maximal 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 " -- (c) 1995-2014 Markus Kuhn -- " + "Licence: " JBG_LICENCE "\n"; + +/* + * The following array specifies for each combination of the 3 + * ordering bits, which ii[] variable represents which dimension + * of s->sde. + */ +static const int iindex[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 */ +}; + +#define _(String) String /* to mark translatable string for GNU gettext */ + +/* + * Array with English ASCII error messages that correspond + * to return values from public functions in this library. + */ +static const char *errmsg[] = { + _("All OK"), /* JBG_EOK */ + _("Reached specified image size"), /* JBG_EOK_INTR */ + _("Unexpected end of input data stream"), /* JBG_EAGAIN */ + _("Not enough memory available"), /* JBG_ENOMEM */ + _("ABORT marker segment encountered"), /* JBG_EABORT */ + _("Unknown marker segment encountered"), /* JBG_EMARKER */ + _("Input data stream contains invalid data"), /* JBG_EINVAL */ + _("Input data stream uses unimplemented JBIG features"), /* JBG_EIMPL */ + _("Incremental BIE does not continue previous one") /* JBG_ENOCONT */ +}; + + +/* + * 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. + * In contrast to C's malloc() and realloc(), but like C's calloc(), + * these functions take two parameters nmemb and size that are multiplied + * before being passed on to the corresponding C function. + * This we can catch all overflows during a size_t multiplication a + * a single place. + */ + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) -1) /* largest value of size_t */ +#endif + +static void *checked_malloc(size_t nmemb, size_t size) +{ + void *p; + + /* 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 instead of abort(). */ + + /* assert that nmemb * size <= SIZE_MAX */ + if (size > SIZE_MAX / nmemb) + abort(); + + p = malloc(nmemb * size); + + if (!p) + abort(); + +#if 0 + fprintf(stderr, "%p = malloc(%lu * %lu)\n", p, + (unsigned long) nmemb, (unsigned long) size); +#endif + + return p; +} + + +static void *checked_realloc(void *ptr, size_t nmemb, size_t size) +{ + void *p; + + /* 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 instead of abort(). */ + + /* assert that nmemb * size <= SIZE_MAX */ + if (size > SIZE_MAX / nmemb) + abort(); + + p = realloc(ptr, nmemb * size); + + if (!p) + abort(); + +#if 0 + fprintf(stderr, "%p = realloc(%p, %lu * %lu)\n", p, ptr, + (unsigned long) nmemb, (unsigned long) size); +#endif + + return p; +} + + +static void checked_free(void *ptr) +{ + free(ptr); + +#if 0 + fprintf(stderr, "free(%p)\n", ptr); +#endif + +} + + + + +/* + * 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(1, 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, which is equivalent to + * y = ceil(x/(2^n)). 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; + + assert(n >= 0 && n < 32); + mask = (1UL << n) - 1; /* the lowest n bits are 1 here */ + return (x >> n) + ((mask & x) != 0); +} + + +/* + * Set L0 (the number of lines in a stripe at lowest resolution) + * to a default value, such that there are about 35 stripes, as + * suggested in Annex C of ITU-T T.82, without exceeding the + * limit 128/2^D suggested in Annex A. + */ +static void jbg_set_default_l0(struct jbg_enc_state *s) +{ + 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; +} + + +/* + * Calculate the number of stripes, as defined in clause 6.2.3 of T.82. + */ +static unsigned long jbg_stripes(unsigned long l0, unsigned long yd, + unsigned long d) +{ + unsigned long y0 = jbg_ceil_half(yd, d); + + return y0 / l0 + (y0 % l0 != 0); +} + + +/* + * Resolution reduction table given by ITU-T T.82 Table 17 + */ + +static 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. + */ + +static 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, +}; + + +/* + * 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; + + assert(x > 0 && y > 0 && planes > 0 && planes < 256); + s->xd = x; + s->yd = y; + s->yd1 = y; /* This is the hight initially announced in BIH. To provoke + generation of NEWLEN for T.85 compatibility tests, + overwrite with new value s->yd1 > s->yd */ + s->planes = planes; + s->data_out = data_out; + s->file = file; + + s->d = 0; + s->dl = 0; + s->dh = s->d; + jbg_set_default_l0(s); + s->mx = 8; + s->my = 0; + s->order = JBG_ILEAVE | JBG_SMID; + s->options = JBG_TPBON | JBG_TPDON | JBG_DPON; + s->comment = NULL; + s->dppriv = jbg_dptable; + s->res_tab = jbg_resred; + + s->highres = (int *) checked_malloc(planes, sizeof(int)); + s->lhp[0] = p; + s->lhp[1] = (unsigned char **) + checked_malloc(planes, sizeof(unsigned char *)); + for (i = 0; i < planes; i++) { + s->highres[i] = 0; + s->lhp[1][i] = (unsigned char *) + checked_malloc(jbg_ceil_half(y, 1), jbg_ceil_half(x, 1+3)); + } + + 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; + jbg_set_default_l0(s); + 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 > 31) + return; + s->d = d; + s->dl = 0; + s->dh = s->d; + jbg_set_default_l0(s); + 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, + unsigned 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 y; /* current line number in highres image */ + unsigned long i; /* current line number within highres stripe */ + unsigned long j; /* current column number in highres image */ + long o; + unsigned a, p, 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; + int reset; + 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 = jbg_ceil_half(hx, 3); + lbpl = jbg_ceil_half(lx, 3); + /* 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; + + /* check whether we can refer to any state of a previous stripe */ + reset = (stripe == 0) || (s->options & JBG_SDRST); + + /* initialize arithmetic encoder */ + se = s->s + plane; + arith_encode_init(se, !reset); + 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) /* the SDRST case is handled at the end */ + 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 (reset) + 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 said < here, fixed in Cor.1/25 */ + 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; + } + assert(s->tx[plane] >= 0); /* i.e., tx can safely be cast to unsigned */ + + /* typical prediction */ + if (s->options & JBG_TPBON) { + ltp = 1; + p1 = hp; + if (i > 0 || !reset) { + 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 (i > 0 || !reset) line_h2 = (long)*(hp - hbpl) << 8; + if (i > 1 || !reset) line_h3 = (long)*(hp - hbpl - hbpl) << 8; + + /* encode line */ + for (j = 0; j < hx; hp++) { + line_h1 |= *hp; + if (j < hbpl * 8 - 8 && (i > 0 || !reset)) { + line_h2 |= *(hp - hbpl + 1); + if (i > 1 || !reset) + 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]) { + if ((unsigned) s->tx[plane] > j) + a = 0; + else { + o = (j - s->tx[plane]) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 4; + } + assert(s->tx[plane] > 23 || + a == ((line_h1 >> (4 + s->tx[plane])) & 0x010)); + arith_encode(se, (((line_h2 >> 10) & 0x3e0) | a | + ((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) { + p = (line_h1 & 0x100) != 0; /* current pixel value */ + c[0] += ((line_h2 & 0x4000) != 0) == p; /* default position */ + assert(!(((line_h2 >> 6) ^ line_h1) & 0x100) == + (((line_h2 & 0x4000) != 0) == p)); + for (t = 5; t <= s->mx && t <= j; t++) { + o = (j - t) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + assert(t > 23 || + (a == p) == !(((line_h1 >> t) ^ line_h1) & 0x100)); + c[t] += a == p; + } + for (; t <= s->mx; t++) { + c[t] += 0 == p; + } + ++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]) { + if ((unsigned) s->tx[plane] > j) + a = 0; + else { + o = (j - s->tx[plane]) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 2; + } + assert(s->tx[plane] > 23 || + a == ((line_h1 >> (6 + s->tx[plane])) & 0x004)); + arith_encode(se, (((line_h3 >> 8) & 0x380) | + ((line_h2 >> 12) & 0x078) | a | + ((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) { + p = (line_h1 & 0x100) != 0; /* current pixel value */ + c[0] += ((line_h2 & 0x4000) != 0) == p; /* default position */ + assert(!(((line_h2 >> 6) ^ line_h1) & 0x100) == + (((line_h2 & 0x4000) != 0) == p)); + for (t = 3; t <= s->mx && t <= j; t++) { + o = (j - t) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + assert(t > 23 || + (a == p) == !(((line_h1 >> t) ^ line_h1) & 0x100)); + c[t] += a == p; + } + for (; t <= s->mx; t++) { + c[t] += 0 == p; + } + ++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 said < here, fixed in Cor.1/25 */ + 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 (i > 1 || !reset) + 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 (i > 1 || !reset) + 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 (i > 0 || !reset) line_h2 = (long)*(hp - hbpl) << 8; + if (i > 1 || !reset) { + 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 (i > 1 || !reset) + line_l3 |= *(lp2 - lbpl + 1); + line_l2 |= *(lp2 + 1); + line_l1 |= *(lp1 + 1); + } + do { /* ... while (j & 15 && j < hx) */ + + 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 (i > 0 || !reset) { + line_h2 |= *(hp - hbpl + 1); + if (i > 1 || !reset) + line_h3 |= *(hp - hbpl - hbpl + 1); + } + } + do { /* ... while (j & 7 && j < hx) */ + 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 { /* ... while (++j & 1 && j < hx) */ + 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]) { + if ((unsigned) s->tx[plane] > j) + a = 0; + else { + o = (j - s->tx[plane]) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 4; + } + assert(s->tx[plane] > 23 || + a == ((line_h1 >> (4 + s->tx[plane])) & 0x010)); + cx = (((line_h1 >> 9) & 0x003) | a | + ((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); + hp++; + } 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((s->options & JBG_SDRST) ? MARKER_SDRST : MARKER_SDNORM, + s->sde[stripe][layer][plane]); + if (s->options & JBG_SDRST) + s->tx[plane] = 0; + + /* 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 hl, ll, hx, hy, lx, ly, hbpl, lbpl; + unsigned char *hp1, *hp2, *hp3, *lp; + unsigned long line_h1, line_h2, line_h3, line_l2; + unsigned long y; /* current line number in lowres image */ + unsigned long i; /* current line number within lowres stripe */ + unsigned long j; /* current column number in lowres image */ + int pix, k, l; + + /* number of lines per stripe in highres image */ + hl = s->l0 << higher_layer; + /* number of lines per stripe in lowres image */ + ll = hl >> 1; + /* 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 = jbg_ceil_half(hx, 3); + lbpl = jbg_ceil_half(lx, 3); + /* 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 (y = 0; y < ly;) { + for (i = 0; i < ll && y < ly; i++, y++) { + if (2*y + 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; + if (i > 0 || (y > 0 && !(s->options & JBG_SDRST))) + line_l2 |= *(lp-lbpl); + for (k = 0; k < 8 && j + k < lx; k += 4) { + if (((j + k) >> 2) < hbpl) { + if (i > 0 || (y > 0 && !(s->options & JBG_SDRST))) + line_h3 |= *hp3; + ++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 apply the resolution reduction + * algorithm first 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 the logic about which SDE has to be + * encoded before resolution reduction is allowed is handled + * here. This approach may be a bit more complex than alternative ways + * of doing it, but it minimizes the amount of temporary memory used. + */ +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; i >> j; 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; i >> j; 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) +{ + unsigned long bpl; + unsigned char buf[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]; + + /* some sanity checks */ + s->order &= JBG_HITOLO | JBG_SEQ | JBG_ILEAVE | JBG_SMID; + order = s->order & (JBG_SEQ | JBG_ILEAVE | JBG_SMID); + if (iindex[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; + /* prevent uint32 overflow: s->l0 * 2 ^ s->d < 2 ^ 32 */ + if (s->d > 31 || (s->d != 0 && s->l0 >= (1UL << (32 - s->d)))) + return; + if (s->yd1 < s->yd) + s->yd1 = s->yd; + if (s->yd1 > s->yd) + s->options |= JBG_VLENGTH; + + /* ensure correct zero padding of bitmap at the final byte of each line */ + if (s->xd & 7) { + bpl = jbg_ceil_half(s->xd, 3); /* 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); + } + + /* prepare BIH */ + buf[0] = s->dl; + buf[1] = s->dh; + buf[2] = s->planes; + buf[3] = 0; + xd = jbg_ceil_half(s->xd, s->d - s->dh); + yd = jbg_ceil_half(s->yd1, s->d - s->dh); + buf[4] = xd >> 24; + buf[5] = (xd >> 16) & 0xff; + buf[6] = (xd >> 8) & 0xff; + buf[7] = xd & 0xff; + buf[8] = yd >> 24; + buf[9] = (yd >> 16) & 0xff; + buf[10] = (yd >> 8) & 0xff; + buf[11] = yd & 0xff; + buf[12] = s->l0 >> 24; + buf[13] = (s->l0 >> 16) & 0xff; + buf[14] = (s->l0 >> 8) & 0xff; + buf[15] = s->l0 & 0xff; + buf[16] = s->mx; + buf[17] = s->my; + buf[18] = s->order; + buf[19] = s->options & 0x7f; + +#if 0 + /* sanitize L0 (if it was set to 0xffffffff for T.85-style NEWLEN tests) */ + if (s->l0 > (s->yd >> s->d)) + s->l0 = s->yd >> s->d; +#endif + + /* calculate number of stripes that will be required */ + s->stripes = jbg_stripes(s->l0, s->yd, s->d); + + /* 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 */ + s->data_out(buf, 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 for each loop */ + is[iindex[order][STRIPE]] = 0; + ie[iindex[order][STRIPE]] = s->stripes - 1; + is[iindex[order][LAYER]] = s->dl; + ie[iindex[order][LAYER]] = s->dh; + is[iindex[order][PLANE]] = 0; + ie[iindex[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[iindex[order][STRIPE]]; + if (s->order & JBG_HITOLO) + layer = s->dh - (ii[iindex[order][LAYER]] - s->dl); + else + layer = ii[iindex[order][LAYER]]; + plane = ii[iindex[order][PLANE]]; + + /* output comment marker segment if there is any pending */ + if (s->comment) { + buf[0] = MARKER_ESC; + buf[1] = MARKER_COMMENT; + buf[2] = s->comment_len >> 24; + buf[3] = (s->comment_len >> 16) & 0xff; + buf[4] = (s->comment_len >> 8) & 0xff; + buf[5] = s->comment_len & 0xff; + s->data_out(buf, 6, s->file); + s->data_out(s->comment, s->comment_len, s->file); + s->comment = NULL; + } + + output_sde(s, stripe, layer, plane); + + /* + * When we generate a NEWLEN test case (s->yd1 > s->yd), output + * NEWLEN after last stripe if we have only a single + * resolution layer or plane (see ITU-T T.85 profile), otherwise + * output NEWLEN before last stripe. + */ + if (s->yd1 > s->yd && + (stripe == s->stripes - 1 || + (stripe == s->stripes - 2 && + (s->dl != s->dh || s->planes > 1)))) { + s->yd1 = s->yd; + yd = jbg_ceil_half(s->yd, s->d - s->dh); + buf[0] = MARKER_ESC; + buf[1] = MARKER_NEWLEN; + buf[2] = yd >> 24; + buf[3] = (yd >> 16) & 0xff; + buf[4] = (yd >> 8) & 0xff; + buf[5] = yd & 0xff; + s->data_out(buf, 6, s->file); +#ifdef DEBUG + fprintf(stderr, "NEWLEN: yd=%lu\n", yd); +#endif + if (stripe == s->stripes - 1) { + buf[1] = MARKER_SDNORM; + s->data_out(buf, 2, s->file); + } + } + + } + + 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", (void *) 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]); + } + + /* clear buffer for index of highres image in lhp */ + checked_free(s->highres); + + return; +} + + +/* + * Convert the error codes used by jbg_dec_in() into an English ASCII string + */ +const char *jbg_strerror(int errnum) +{ + errnum >>= 4; + if (errnum < 0 || (unsigned) errnum >= sizeof(errmsg)/sizeof(errmsg[0])) + return "Unknown error code passed to jbg_strerror()"; + + return errmsg[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, in which case + * this code cannot 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; + long o; + unsigned a; + int n; + int pix, cx = 0, slntp, tx; + + /* SDE loop variables */ + stripe = s->ii[iindex[s->order & 7][STRIPE]]; + layer = s->ii[iindex[s->order & 7][LAYER]]; + plane = s->ii[iindex[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 = jbg_ceil_half(hx, 3); + lbpl = jbg_ceil_half(lx, 3); + /* 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; + +#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", + (void *) s, (void *) data, (long) len, stripe, layer, plane); +#endif + + if (s->x == 0 && s->i == 0 && + (stripe == 0 || s->reset[plane][layer - s->dl]) && s->pseudo) { + s->tx[plane][layer - s->dl] = s->ty[plane][layer - s->dl] = 0; + s->lntp[plane][layer - s->dl] = 1; + } + + if (layer == 0) { + + /* + * Decode lowest resolution layer + */ + + for (; s->i < hl && y < hy; s->i++, y++) { + + /* adaptive template changes */ + if (x == 0 && s->pseudo) + 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]; + assert(tx >= 0); /* i.e., tx can safely be cast to unsigned */ + + /* typical prediction */ + if (s->options & JBG_TPBON && s->pseudo) { + slntp = arith_decode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX); + if (slntp < 0) + 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 '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; + } + /* this line is 'not typical' and has to be coded completely */ + } + s->pseudo = 0; + + /* + * 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) { + if ((unsigned) tx > x) + a = 0; + else if (tx < 8) + a = ((line_h1 >> (tx - 5)) & 0x010); + else { + o = (x - tx) - (x & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 4; + } + assert(tx > 31 || + a == ((line_h1 >> (tx - 5)) & 0x010)); + pix = arith_decode(se, (((line_h2 >> 9) & 0x3e0) | a | + (line_h1 & 0x00f))); + } else + pix = arith_decode(se, (((line_h2 >> 9) & 0x3f0) | + (line_h1 & 0x00f))); + if (pix < 0) + goto leave; + line_h1 = (line_h1 << 1) | pix; + line_h2 <<= 1; + } while ((++x & 7) && x < hx); + } else { + /* three line template */ + do { + if (tx) { + if ((unsigned) tx > x) + a = 0; + else if (tx < 8) + a = ((line_h1 >> (tx - 3)) & 0x004); + else { + o = (x - tx) - (x & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 2; + } + assert(tx > 31 || + a == ((line_h1 >> (tx - 3)) & 0x004)); + pix = arith_decode(se, (((line_h3 >> 7) & 0x380) | + ((line_h2 >> 11) & 0x078) | a | + (line_h1 & 0x003))); + } else + pix = arith_decode(se, (((line_h3 >> 7) & 0x380) | + ((line_h2 >> 11) & 0x07c) | + (line_h1 & 0x003))); + if (pix < 0) + 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]; + + /* 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) { + if ((s->lntp[plane][layer - s->dl] = arith_decode(se, TPDCX)) < 0) + 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) >> (tx - 3)) & 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 (pix < 0) + 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 to the decoder a new BIE fragment of len bytes starting at data. + * + * Unless cnt is NULL, *cnt will contain the number of actually read bytes + * on return. + * + * Normal return values: + * + * JBG_EAGAIN All data bytes provided so far have been processed + * (*cnt == len) but the end of the data stream has + * not yet been recognized. Call the function again + * with additional BIE bytes. + * JBG_EOK The function has reached the end of a and + * a full image has been decoded. The function can + * be called again with data from the next BIE, if + * there exists one, in order to get to a higher + * resolution layer. The remaining len - *cnt bytes + * of the previous data block will then have to passed + * to this function again if len > *cnt. + * JBG_EOK_INTR Parsing the BIE has been interrupted as had been + * requested by a jbg_dec_maxsize() specification. + * This function can be called again with the + * rest of the BIE to continue the decoding process. + * The remaining len - *cnt bytes of the previous + * data block will then have to be passed to this + * function again if len > *cnt. + * + * Any other return value indicates that the decoding process was + * aborted by a serious problem and the only function you can then + * still call is jbg_dec_free() in order to remove the mess, and + * jbg85_strerror() to find out what to tell the user. (Looking at the + * least significant bits of the return value will provide additional + * information by identifying which test exactly has failed.) + */ +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]; + size_t dummy_cnt; + unsigned char *dppriv; + + 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; + /* test whether this looks like a valid JBIG header at all */ + if (s->buffer[1] < s->buffer[0]) + return JBG_EINVAL | 1; + if (s->buffer[3] != 0) return JBG_EINVAL | 2; /* padding != 0 */ + if ((s->buffer[18] & 0xf0) != 0) return JBG_EINVAL | 3; /* padding != 0 */ + if ((s->buffer[19] & 0x80) != 0) return JBG_EINVAL | 4; /* padding != 0 */ + if (s->buffer[0] != s->d + 1) + return JBG_ENOCONT | 1; + 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 | 2; + 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 | 3; + 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]); + /* ITU-T T.85 trick not directly implemented by decoder; for full + * T.85 compatibility with respect to all NEWLEN marker scenarios, + * preprocess BIE with jbg_newlen() before passing it to the decoder, + * or consider using the decoder found in jbig85.c instead. */ + if (s->yd == 0xffffffff) + return JBG_EIMPL | 1; + if (!s->planes) return JBG_EINVAL | 5; + if (!s->xd) return JBG_EINVAL | 6; + if (!s->yd) return JBG_EINVAL | 7; + if (!s->l0) return JBG_EINVAL | 8; + /* prevent uint32 overflow: s->l0 * 2 ^ s->d < 2 ^ 32 */ + if (s->d > 31) + return JBG_EIMPL | 2; + if ((s->d != 0 && s->l0 >= (1UL << (32 - s->d)))) + return JBG_EIMPL | 3; + s->mx = s->buffer[16]; + if (s->mx > 127) + return JBG_EINVAL | 9; + s->my = s->buffer[17]; +#if 0 + if (s->my > 0) + return JBG_EIMPL | 4; +#endif + s->order = s->buffer[18]; + if (iindex[s->order & 7][0] < 0) + return JBG_EINVAL | 10; + /* HITOLO and SEQ currently not yet implemented */ + if (s->dl != s->d && (s->order & JBG_HITOLO || s->order & JBG_SEQ)) + return JBG_EIMPL | 5; + s->options = s->buffer[19]; + + /* calculate number of stripes that will be required */ + s->stripes = jbg_stripes(s->l0, s->yd, s->d); + + /* some initialization */ + s->ii[iindex[s->order & 7][STRIPE]] = 0; + s->ii[iindex[s->order & 7][LAYER]] = s->dl; + s->ii[iindex[s->order & 7][PLANE]] = 0; + if (s->dl == 0) { + s->s = (struct jbg_ardec_state **) + checked_malloc(s->planes, sizeof(struct jbg_ardec_state *)); + s->tx = (int **) checked_malloc(s->planes, sizeof(int *)); + s->ty = (int **) checked_malloc(s->planes, sizeof(int *)); + s->reset = (int **) checked_malloc(s->planes, sizeof(int *)); + s->lntp = (int **) checked_malloc(s->planes, sizeof(int *)); + s->lhp[0] = (unsigned char **) + checked_malloc(s->planes, sizeof(unsigned char *)); + s->lhp[1] = (unsigned char **) + checked_malloc(s->planes, sizeof(unsigned char *)); + for (i = 0; i < s->planes; i++) { + s->s[i] = (struct jbg_ardec_state *) + checked_malloc(s->d - s->dl + 1, sizeof(struct jbg_ardec_state)); + s->tx[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->ty[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->reset[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->lntp[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->lhp[ s->d & 1][i] = (unsigned char *) + checked_malloc(s->yd, jbg_ceil_half(s->xd, 3)); + s->lhp[(s->d-1) & 1][i] = (unsigned char *) + checked_malloc(jbg_ceil_half(s->yd, 1), jbg_ceil_half(s->xd, 1+3)); + } + } else { + for (i = 0; i < s->planes; i++) { + s->s[i] = (struct jbg_ardec_state *) + checked_realloc(s->s[i], s->d - s->dl + 1, + sizeof(struct jbg_ardec_state)); + s->tx[i] = (int *) checked_realloc(s->tx[i], + s->d - s->dl + 1, sizeof(int)); + s->ty[i] = (int *) checked_realloc(s->ty[i], + s->d - s->dl + 1, sizeof(int)); + s->reset[i] = (int *) checked_realloc(s->reset[i], + s->d - s->dl + 1, sizeof(int)); + s->lntp[i] = (int *) checked_realloc(s->lntp[i], + s->d - s->dl + 1, sizeof(int)); + s->lhp[ s->d & 1][i] = (unsigned char *) + checked_realloc(s->lhp[ s->d & 1][i], + s->yd, jbg_ceil_half(s->xd, 3)); + s->lhp[(s->d-1) & 1][i] = (unsigned char *) + checked_realloc(s->lhp[(s->d-1) & 1][i], + jbg_ceil_half(s->yd, 1), jbg_ceil_half(s->xd, 1+3)); + } + } + 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); + if (!s->dppriv || s->dppriv == jbg_dptable) + s->dppriv = (char *) checked_malloc(1728, sizeof(char)); + while (s->bie_len < 20 + 1728 && *cnt < len) + s->dppriv[s->bie_len++ - 20] = data[(*cnt)++]; + if (s->bie_len < 20 + 1728) + return JBG_EAGAIN; + dppriv = (unsigned char *) s->dppriv; + s->dppriv = (char *) checked_malloc(6912, sizeof(char)); + jbg_dppriv2int(s->dppriv, dppriv); + checked_free(dppriv); + } + + /* + * 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 | 11; + if (s->at_ty[s->at_moves] != 0) + return JBG_EIMPL | 6; + s->at_moves++; + } else + return JBG_EIMPL | 7; /* more than JBG_ATMOVES_MAX ATMOVES */ + 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) return JBG_EINVAL | 12; + if (!(s->options & JBG_VLENGTH)) return JBG_EINVAL | 13; + s->yd = y; + /* calculate again number of stripes that will be required */ + s->stripes = jbg_stripes(s->l0, s->yd, s->d); + 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[iindex[s->order & 7][PLANE]]] + + s->ii[iindex[s->order & 7][LAYER]] - s->dl, + s->ii[iindex[s->order & 7][STRIPE]] != s->stripes - 1 + && s->buffer[1] != MARKER_SDRST); + + s->reset[s->ii[iindex[s->order & 7][PLANE]]] + [s->ii[iindex[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[iindex[s->order & 7][STRIPE]] = 0; + ie[iindex[s->order & 7][STRIPE]] = s->stripes - 1; + is[iindex[s->order & 7][LAYER]] = s->dl; + ie[iindex[s->order & 7][LAYER]] = s->d; + is[iindex[s->order & 7][PLANE]] = 0; + ie[iindex[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) { +#ifdef DEBUG + fprintf(stderr, "This was the final SDE in this BIE, " + "%ld bytes left.\n", (long) (len - *cnt)); +#endif + s->bie_len = 0; + return JBG_EOK; + } + + /* check whether we have to abort because of xmax/ymax */ + if (iindex[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 | 14; + } + + } + } /* 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. Returns 0 if + * there is no image available yet. + */ +unsigned long jbg_dec_getwidth(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return 0; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return 0; + 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. Returns 0 if + * there is no image available yet. + */ +unsigned long jbg_dec_getheight(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return 0; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return 0; + 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. Returns NULL if + * there is no image available yet. + */ +unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane) +{ + if (s->d < 0) + return NULL; + if (iindex[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. + */ +unsigned long jbg_dec_getsize(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return 0; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return 0; + else + return + jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1) + 3) * /* overflow risk? */ + jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); + } + + return jbg_ceil_half(s->xd, 3) * 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(). + */ +unsigned long jbg_dec_getsize_merged(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return 0; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return 0; + else + return + jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) * /* overflow risk? */ + 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]); + if (s->dppriv && s->dppriv != jbg_dptable) + checked_free(s->dppriv); + + 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 long bpl = jbg_ceil_half(x, 3); /* bytes per line in dest plane */ + unsigned long line, i; + unsigned k = 8; + int p; + 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++ << 8; + /* 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 (((msb - 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 + unsigned long bpl, line, i; + unsigned k = 8; + int p; + 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; + bpl = jbg_ceil_half(x, 3); /* bytes per line in src plane */ + + if (iindex[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 */ + v = 0; + for (p = 0; p < s->planes;) { /* dest bytes loop */ + do { + v = (v << 1) | + (((src[p][bpl * line + i] >> (7 - k)) & 1) ^ + (use_graycode & v)); + } while ((s->planes - ++p) & 7); + *bp++ = v; + if (bp - buf == BUFLEN) { + data_out(buf, BUFLEN, file); + bp = buf; + } + } + } + } + } + + if (bp - buf > 0) + data_out(buf, bp - buf, file); + + return; +} + + +/* + * Given a pointer p to the first byte of either a marker segment or a + * PSCD, as well as the length len of the remaining data, return + * either the pointer to the first byte of the next marker segment or + * PSCD, or p+len if this was the last one, or NULL if some error was + * encountered. Possible errors are: + * + * - not enough bytes left for complete marker segment + * - no marker segment terminates the PSCD + * - unknown marker code encountered + * + */ +static unsigned char *jbg_next_pscdms(unsigned char *p, size_t len) +{ + unsigned char *pp; + unsigned long l; + + if (len < 2) + return NULL; /* not enough bytes left for complete marker segment */ + + if (p[0] != MARKER_ESC || p[1] == MARKER_STUFF) { + do { + while (p[0] == MARKER_ESC && p[1] == MARKER_STUFF) { + p += 2; + len -= 2; + if (len < 2) + return NULL; /* not enough bytes left for complete marker segment */ + } + assert(len >= 2); + pp = (unsigned char *) memchr(p, MARKER_ESC, len - 1); + if (!pp) + return NULL; /* no marker segment terminates the PSCD */ + l = pp - p; + assert(l < len); + p += l; + len -= l; + } while (p[1] == MARKER_STUFF); + } else { + switch (p[1]) { + case MARKER_SDNORM: + case MARKER_SDRST: + case MARKER_ABORT: + return p + 2; + case MARKER_NEWLEN: + if (len < 6) + return NULL; /* not enough bytes left for complete marker segment */ + return p + 6; + case MARKER_ATMOVE: + if (len < 8) + return NULL; /* not enough bytes left for complete marker segment */ + return p + 8; + case MARKER_COMMENT: + if (len < 6) + return NULL; /* not enough bytes left for complete marker segment */ + l = (((long) p[2] << 24) | ((long) p[3] << 16) | + ((long) p[4] << 8) | (long) p[5]); + if (len - 6 < l) + return NULL; /* not enough bytes left for complete marker segment */ + return p + 6 + l; + default: + /* unknown marker sequence encountered */ + return NULL; + } + } + + return p; +} + + +/* + * Scan a complete BIE for a NEWLEN marker segment, then read the new + * YD value found in it and use it to overwrite the one in the BIE + * header. Use this procedure if a BIE initially declares an + * unreasonably high provisional YD value (e.g., 0xffffffff) or + * depends on the fact that section 6.2.6.2 of ITU-T T.82 says that a + * NEWLEN marker segment "could refer to a line in the immediately + * preceding stripe due to an unexpected termination of the image or + * the use of only such stripe". ITU-T.85 explicitely suggests the + * use of this for fax machines that start transmission before having + * encountered the end of the page. None of this is necessary for + * BIEs produced by JBIG-KIT, which normally does not use NEWLEN. + */ +int jbg_newlen(unsigned char *bie, size_t len) +{ + unsigned char *p = bie + 20; + int i; + unsigned long y, yn; + + if (len < 20) + return JBG_EAGAIN; + if ((bie[19] & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) + == (JBG_DPON | JBG_DPPRIV)) + p += 1728; /* skip DPTABLE */ + if (p >= bie + len) + return JBG_EAGAIN; + + while ((p = jbg_next_pscdms(p, len - (p - bie)))) { + if (p == bie + len) + return JBG_EOK; + else if (p[0] == MARKER_ESC) + switch (p[1]) { + case MARKER_NEWLEN: + y = (((long) bie[ 8] << 24) | ((long) bie[ 9] << 16) | + ((long) bie[10] << 8) | (long) bie[11]); + yn = (((long) p[2] << 24) | ((long) p[3] << 16) | + ((long) p[4] << 8) | (long) p[5]); + if (yn > y) return JBG_EINVAL | 12; + /* overwrite YD in BIH with YD from NEWLEN */ + for (i = 0; i < 4; i++) { + bie[8+i] = p[2+i]; + } + return JBG_EOK; + case MARKER_ABORT: + return JBG_EABORT; + } + } + return JBG_EINVAL | 0; +} diff --git a/converter/other/jbig/libjbig/jbig.txt b/converter/other/jbig/libjbig/jbig.txt new file mode 100644 index 00000000..bdc14b17 --- /dev/null +++ b/converter/other/jbig/libjbig/jbig.txt @@ -0,0 +1,810 @@ + +Using the JBIG-KIT library +-------------------------- + +Markus Kuhn -- 2013-09-10 + + +This text explains how to use the functions provided by the JBIG-KIT +portable image compression library jbig.c in your application +software. The jbig.c library is a full-featured implementation of the +JBIG1 standard aimed at applications that can hold the entire +uncompressed and compressed image in RAM. + +[For applications that require only the single-bit-per-pixel "fax +subset" of the JBIG1 standard defined in ITU-T Recommendation T.85 +, the alternative implementation +found in jbig85.c may be preferable. It keeps not more than three +lines of the uncompressed image in RAM, which makes it particularly +suitable for embedded applications. For information on how to use +jbig85.c, please refer to the separate documentation file jbig85.txt.] + + +1 Introduction to JBIG + +We start with a short introduction to JBIG1. More detailed information +is provided in the "Introduction and overview" section of the JBIG1 +standard. Information on how to obtain a copy of the standard is +available from or +. + +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 one with the highest. Each +next higher resolution layer has twice the number of rows and columns. +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). Each SDE encodes the content of one single stripe in +one plane of one resolution layer. Between the SDEs, other information +blocks (called floating marker segments) can also be present. They are +used to 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 | + | | + +------------------------------------------------+ + | | + | optional floating marker segments | + | | + +------------------------------------------------+ + | | + | 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 by the +standard 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 pbmtojbg, jbgtopbm, pbmtojbg85, and jbgtopbm85 +conversion tools do that are provided in this package as demonstration +applications. However, as the BIE format has been designed for a large +number of very different applications, and 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. Many 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 format on a typeless file system and to allow + automatic distinction from other compression algorithms + + - no standardized way to encode additional information such as a + textual description, information about the meaning of various bit + planes, the physical size and resolution of the document, etc. + + - a checksum to ensure image integrity + + - encryption and signature mechanisms + + - many things more + +Raw BIE data streams alone may therefore not be a suitable format for +document archiving and exchange. A standard format for this purpose +would typically combine a BIE representing the image data 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 to +also hold JBIG compressed data. + +On the other hand, in e.g. database applications, a BIE might be +stored directly in a binary variable-length field. Auxiliary +information would then be stored in other fields of the same record, +to simplify search operations. + + +2 Compressing an image + +2.1 Format of the source image + +To be processed by the jbig.c encoder, the image has to be present in +memory as separate bitmap planes. Each byte of a bitmap contains eight +pixels, where the most significant bit represents the leftmost of +these. 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 handled +directly by the Xlib library of the X Window System. + +As JBIG can also handle images with multiple bit planes, the jbig.c +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 +colour of an image, in other words, 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 colours should +be encoded. + +For grey-scale 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 it +has the property that the representations of the integer numbers i and +(i+1) always differ in exactly one 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 grey-scale 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.c 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 object-oriented programming principles. +You have to declare a variable (object) + + struct jbg_enc_state s; + +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 that you want + to initialize. + + x The width of your image in pixels. + + y The height of your image in pixels (lines). + + 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 that the encoder will + call during the compression process by in order to + deliver the BIE data to your application. The + parameters of the function data_out are a pointer + start to the new block of data being 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(). Typically, 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 that is passed on to data_out() + and can be used, for instance, to allow 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() in several calls. +After jbg_enc_out has returned, a call to the destructor function + + void jbg_enc_free(struct jbg_enc_state *s); + +will release any heap memory allocated by the previous functions. + + +A minimal example application, which sends the BIE of the above bitmap +to stdout, looks like this: + +--------------------------------------------------------------------------- +/* A sample JBIG encoding application */ + +#include +#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 table 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 +document with 60-micrometer pixels has to be stored, and the lowest +resolution layer shall have 240-micrometer pixels, so that a screen +previewer can directly decompress only the required resolution, then a +call + + jbg_enc_layers(&se, 2); + +will cause three layers with 240, 120 and 60 micrometers resolution to +be generated. + +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. For instance, if 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, call + + jbg_enc_lrange(&se, 0, 0); + +and before writing the second BIE with jbg_enc_out(), call + + 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 that will represent +the input image. This way, jbg_enc_lrange(&se, -1, -1) can be used to +query the layer of the full image resolution. + +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.c decoder currently does 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.c decoder. + + JBG_SMID In case there exist several bit planes, then the order of + the stripes is determined by three 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 may be somewhat confusing, but the following +table (see also Table 11 in ITU-T T.82) clarifies 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.c and is off by + default. + + JBG_TPDON This activates the "typical prediction" algorithm + for differential layers which avoids that large + areas of equal colour 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 that might 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 neighbour pixels, the + corresponding lower resolution pixels and the + resolution reduction algorithm. This is also + activated by default and one reason for deactivating + it would be if the default resolution reduction + algorithm were replaced by another 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 is 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. JBIG-KIT now supports the full range of possible mx values up +to 127 in the encoder and decoder, but my is at the moment ignored and +always set to 0. As the standard requires of all decoder +implementations only to support maximum values mx = 16 and my = 0, +higher values should normally be avoided in order to guarantee +interoperability. The ITU-T T.85 profile for JBIG in fax machines +requires support for mx = 127 and my = 0. Default is mx = 8 and my = +0. If any of the parameters order, options, mx or my is negative, or +l0 is zero, then the corresponding current value remains 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 grey-scale 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 bit planes. The dest array of pointers to +these bit planes 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 bit planes 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.c +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 will be 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 + + unsigned long jbg_dec_getwidth(struct jbg_dec_state *s); + unsigned 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); + unsigned 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 bit planes 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 + + unsigned 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); + +returns a pointer to a short single line test message that 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 a JBIG image. The po/ subdirectory contains *.po +files that translate the English ASCII strings returned by +jbg_strerror() into other languages (e.g., for use with GNU gettext). +The four least-significant bits of the return value of jbg_dec_in() +may contain additional detailed technical information about the exact +test that spotted the error condition (see source code for details), +i.e. more than the text message returned by jbg_strerror() reveals. +Therefore it may be useful to display the return value itself as a +hexadecimal number, in addition to the string returned by +jbg_strerror(). + +The current implementation of the jbig.c decoder has the following +limitations: + + - The maximal vertical offset MY of the adaptive template pixel + must be zero. + + - HITOLO and SEQ bits must not be set in the order value. + + - Not more than JBG_ATMOVES_MAX (currently set to 64) ATMOVE + marker segments can be handled per stripe. + + - the number D of differential layers must be less than 32 + +None of the above limitations can be exceeded by a JBIG data stream +that conforms to the ITU-T T.85 application profile for the use of +JBIG1 in fax machines. + +The current implementation of the jbig.c decoder does not impose any +limits on the image size that it will process, as long as malloc() is +able to allocate enough heap space for the resulting bitmaps. The only +exception is that jbg_dec_in() will return "Input data stream uses +unimplemented JBIG features" (JBG_EIMPL | 1) if Y_D equals 0xffffffff, +which is an extreme value commonly used to encode images according to +ITU-T T.85 where the height was unknown when the BIH was emitted. +After jbg_dec_in() received the 20-byte long BIH at the start of the +BIE, it will malloc() to allocate enough memory to hold the requested +image planes and layers. If you want to defend your application +against excessive image-size parameters in a received BIH, then do +make sure that you check X_D, Y_D, and P against appropriate safety +limits before handing over the BIH to jbg_dec_in(). + +There are two more limitations of the current implementation of the +jbig.c decoder that might cause problems with processing JBIG data +stream that conform to ITU-T T.85: + + - The jbig.c decoder was designed to operate incrementally. + Each received byte is processed immediately as soon as it arrives. + As a result, it does not look beyond the SDRST/SDNORM at the end + of all stripes for any immediately following NEWLEN marker that + might reduce the number of lines encoded by the current stripe. + However section 6.2.6.2 of ITU-T T.82 says that a NEWLEN marker + segment "could refer to a line in the immediately preceding stripe + due to an unexpected termination of the image or the use of only + such stripe", and ITU-T.85 explicitly suggests the use of this + for fax machines that start transmission before having encountered + the end of the page. + + - The image size initially indicated in the BIE header is used to + allocate memory for a bitmap of this size. This means that BIEs + that set initially Y_D = 0xffffffff (as suggested in ITU-T T.85 + for fax machines that do not know the height of the page at the + start of the transmission) cannot be decoded directly by this + version. + +For both issues, there is a workaround available: + +If you encounter a BIE that has in the header the VLENGTH=1 option bit +set, then first wait until you have received the entire BIE and stored +it in memory. Then call the function + + int jbg_newlen(unsigned char *bie, size_t len); + +where bie is a pointer to the first byte of the BIE and len its length +in bytes. This function will scan the entire BIE for the first NEWLEN +marker segment. It will then take the updated image-height value YD +from it and use it to overwrite the YD value in the BIE header. The +jbg_newlen() can return some of the same error codes as jbg_dec_in(), +namely JBG_EOK if everything went fine, JBG_EAGAIN is the data +provided is too short to be a valid BIE, JBG_EINVAL if a format error +was encountered, and JBG_EABORT if an ABORT marker segment was found. +After having patched the image-height value in the BIE using +jbg_newlen(), simply hand over the BIE as usual to jbg_dec_in(). + +In general, for applications where NEWLEN markers can appear, in +particular fax reception, you should consider using the jbig85.c +decoder instead, as it can process BIEs with NEWLEN markers in a +single pass. + +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) + + +Please quote the above if you use JBIG-KIT in your research project. + +*** Happy compressing *** + +[end] diff --git a/converter/other/jbig/libjbig/jbig_ar.c b/converter/other/jbig/libjbig/jbig_ar.c new file mode 100644 index 00000000..d23a317d --- /dev/null +++ b/converter/other/jbig/libjbig/jbig_ar.c @@ -0,0 +1,417 @@ +/* + * Arithmetic encoder and decoder of the portable JBIG + * compression library + * + * Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/jbigkit/ + * + * This module implements a portable standard C arithmetic encoder + * and decoder used by the JBIG lossless bi-level image compression + * algorithm as specified in International Standard ISO 11544:1993 + * and ITU-T Recommendation T.82. + * + * 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. + */ + +#include +#include "jbig_ar.h" + +/* + * Probability estimation tables for the arithmetic encoder/decoder + * given by ITU T.82 Table 24. + */ + +static short lsztab[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 +}; + +static unsigned char nmpstab[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 nlpstab[] contain NLPS value, + * most significant bit (mask 0x80) contains SWTCH bit + */ +static unsigned char nlpstab[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 +}; + +/* + * The next functions implement the arithmedic encoder and decoder + * required for JBIG. The same algorithm is also used in the arithmetic + * variant of JPEG. + */ + +/* marker codes */ +#define MARKER_STUFF 0x00 +#define MARKER_ESC 0xff + +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; +} + + +void arith_encode_flush(struct jbg_arenc_state *s) +{ + unsigned long temp; + + /* 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; +} + + +void arith_encode(struct jbg_arenc_state *s, int cx, int pix) +{ + register unsigned lsz, ss; + register unsigned char *st; + long temp; + + assert(cx >= 0 && cx < 4096); + st = s->st + cx; + ss = *st & 0x7f; + assert(ss < 113); + lsz = lsztab[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 ^= nlpstab[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 |= nmpstab[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; +} + + +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->startup = 1; + s->nopadding = 0; + return; +} + +/* + * Decode and return one symbol from the provided PSCD byte stream + * that starts in s->pscd_ptr and ends in the byte before s->pscd_end. + * The context cx is a 12-bit integer in the range 0..4095. This + * function will advance s->pscd_ptr each time it has consumed all + * information from that PSCD byte. + * + * If a symbol has been decoded successfully, the return value will be + * 0 or 1 (depending on the symbol). + * + * If the decoder was not able to decode a symbol from the provided + * PSCD, then the return value will be -1, and two cases can be + * distinguished: + * + * s->pscd_ptr == s->pscd_end: + * + * The decoder has used up all information in the provided PSCD + * bytes. Further PSCD bytes have to be provided (via new values of + * s->pscd_ptr and/or s->pscd_end) before another symbol can be + * decoded. + * + * s->pscd_ptr == s->pscd_end - 1: + * + * The decoder has used up all provided PSCD bytes except for the + * very last byte, because that has the value 0xff. The decoder can + * at this point not yet tell whether this 0xff belongs to a + * MARKER_STUFF sequence or marks the end of the PSCD. Further PSCD + * bytes have to be provided (via new values of s->pscd_ptr and/or + * s->pscd_end), including the not yet processed 0xff byte, before + * another symbol can be decoded successfully. + * + * If s->nopadding != 0, the decoder will return -2 when it reaches + * the first two bytes of the marker segment that follows (and + * terminates) the PSCD, but before decoding the first symbol that + * depends on a bit in the input data that could have been the result + * of zero padding, and might, therefore, never have been encoded. + * This gives the caller the opportunity to lookahead early enough + * beyond a terminating SDNORM/SDRST for a trailing NEWLEN (as + * required by T.85) before decoding remaining symbols. Call the + * decoder again afterwards as often as necessary (leaving s->pscd_ptr + * pointing to the start of the marker segment) to retrieve any + * required remaining symbols that might depend on padding. + * + * [Note that each PSCD can be decoded into an infinitely long + * sequence of symbols, because the encoder might have truncated away + * an arbitrarily long sequence of trailing 0x00 bytes, which the + * decoder will append automatically as needed when it reaches the end + * of the PSCD. Therefore, the decoder cannot report any end of the + * symbol sequence and other means (external to the PSCD and + * arithmetic decoding process) are needed to determine that.] + */ + +int arith_decode(struct jbg_ardec_state *s, int cx) +{ + register unsigned lsz, ss; + register unsigned char *st; + int pix; + + /* renormalization */ + while (s->a < 0x8000 || s->startup) { + while (s->ct <= 8 && s->ct >= 0) { + /* first we can move a new byte into s->c */ + if (s->pscd_ptr >= s->pscd_end) { + return -1; /* more bytes needed */ + } + if (*s->pscd_ptr == 0xff) + if (s->pscd_ptr + 1 >= s->pscd_end) { + return -1; /* final 0xff byte not processed */ + } else { + if (*(s->pscd_ptr + 1) == MARKER_STUFF) { + s->c |= 0xffL << (8 - s->ct); + s->ct += 8; + s->pscd_ptr += 2; + } else { + s->ct = -1; /* start padding with zero bytes */ + if (s->nopadding) { + s->nopadding = 0; + return -2; /* subsequent symbols might depend on zero padding */ + } + } + } + else { + s->c |= (long)*(s->pscd_ptr++) << (8 - s->ct); + s->ct += 8; + } + } + s->c <<= 1; + s->a <<= 1; + if (s->ct >= 0) s->ct--; + if (s->a == 0x10000L) + s->startup = 0; + } + + st = s->st + cx; + ss = *st & 0x7f; + assert(ss < 113); + lsz = lsztab[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 ^= nlpstab[ss]; + } else { + pix = *st >> 7; + *st &= 0x80; + *st |= nmpstab[ss]; + } + } + else { + /* LPS_EXCHANGE */ + if (s->a < lsz) { + s->c -= s->a << 16; + s->a = lsz; + pix = *st >> 7; + *st &= 0x80; + *st |= nmpstab[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 ^= nlpstab[ss]; + } + } + + return pix; +} 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 +#include + #include "pm_c_util.h" #include "pam.h" #include "shhopt.h" #include "nstring.h" #include "mallocvar.h" -#include #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 +#include + #include "pm_c_util.h" #include "pam.h" #include "shhopt.h" #include "nstring.h" #include "mallocvar.h" -#include #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 */ -#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 ] [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 ] [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-2)&&(in=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 #include #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; diff --git a/converter/pbm/cmuwmtopbm.c b/converter/pbm/cmuwmtopbm.c index 1f2d21f1..ccf8cfc9 100644 --- a/converter/pbm/cmuwmtopbm.c +++ b/converter/pbm/cmuwmtopbm.c @@ -48,20 +48,20 @@ readCmuwmHeader(FILE * const ifP, rc = pm_readbiglong(ifP, &l); if (rc == -1 ) - pm_error(initReadError); + pm_error("%s", initReadError); if ((uint32_t)l != cmuwmMagic) pm_error("bad magic number in CMU window manager file"); rc = pm_readbiglong(ifP, &l); if (rc == -1) - pm_error(initReadError); + pm_error("%s", initReadError); *colsP = l; rc = pm_readbiglong(ifP, &l); if (rc == -1 ) - pm_error(initReadError); + pm_error("%s", initReadError); *rowsP = l; rc = pm_readbigshort(ifP, &s); if (rc == -1) - pm_error(initReadError); + pm_error("%s", initReadError); *depthP = s; } diff --git a/converter/pbm/pbmtoppa/Makefile b/converter/pbm/pbmtoppa/Makefile index 5f205230..cf31ded6 100644 --- a/converter/pbm/pbmtoppa/Makefile +++ b/converter/pbm/pbmtoppa/Makefile @@ -9,17 +9,18 @@ include $(BUILDDIR)/config.mk all: pbmtoppa -BINARIES = pbmtoppa +PORTBINARIES = pbmtoppa + +BINARIES = $(PORTBINARIES) MERGEBINARIES = $(BINARIES) -OBJECTS = pbmtoppa.o ppa.o pbm.o cutswath.o -MERGE_OBJECTS = pbmtoppa.o2 ppa.o pbm.o cutswath.o +ADDL_OBJECTS = ppa.o pbm.o cutswath.o -include $(SRCDIR)/common.mk +OBJECTS = pbmtoppa.o $(ADDL_OBJECTS) -pbmtoppa: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o pbmtoppa $(OBJECTS) \ - -lm $(shell $(LIBOPT) $(NETPBMLIB)) $(LDFLAGS) $(LDLIBS) \ - $(RPATH) $(LADD) +MERGE_OBJECTS = pbmtoppa.o2 $(ADDL_OBJECTS) + +include $(SRCDIR)/common.mk +pbmtoppa: $(OBJECTS) diff --git a/converter/ppm/ilbm.h b/converter/ppm/ilbm.h index 68657956..dbe47758 100644 --- a/converter/ppm/ilbm.h +++ b/converter/ppm/ilbm.h @@ -23,7 +23,7 @@ typedef struct { #define mskNone 0 #define mskHasMask 1 #define mskHasTransparentColor 2 -#define mskLasso 3 /* not supported */ +#define mskLasso 3 /* can't handle this */ #define mskMAXKNOWN mskLasso static const char * mskNAME[] = { "none", "mask plane", "transparent color", "lasso" @@ -127,8 +127,8 @@ typedef struct { #define CLUT_RED 1 #define CLUT_GREEN 2 #define CLUT_BLUE 3 -#define CLUT_HUE 4 /* not supported */ -#define CLUT_SAT 5 /* not supported */ +#define CLUT_HUE 4 /* can't handle this */ +#define CLUT_SAT 5 /* can't handle this */ /* unofficial DCOL chunk for direct-color */ diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile index 4f244ae9..49aeb7f8 100644 --- a/converter/ppm/ppmtompeg/Makefile +++ b/converter/ppm/ppmtompeg/Makefile @@ -38,7 +38,13 @@ endif # -DHEINOUS_DEBUG_MODE # -MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o +MP_BASE_OBJS = \ + mfwddct.o \ + postdct.o \ + huff.o \ + bitio.o \ + mheaders.o \ + MP_ENCODE_OBJS = \ frames.o \ iframe.o \ @@ -46,11 +52,24 @@ MP_ENCODE_OBJS = \ bframe.o \ psearch.o \ bsearch.o \ - block.o + block.o \ + +MP_OTHER_OBJS = \ + mpeg.o \ + subsample.o \ + param.o \ + rgbtoycc.o \ + readframe.o \ + combine.o \ + jrevdct.o \ + frame.o \ + fsize.o \ + frametype.o \ + specifics.o \ + rate.o \ + opts.o \ + input.o \ -MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \ - readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \ - specifics.o rate.o opts.o input.o ifeq ($(OMIT_NETWORK),Y) MP_OTHER_OBJS += noparallel.o else @@ -62,14 +81,19 @@ else MP_OTHER_OBJS += gethostname.o endif -NONMAIN_OBJS = $(MP_BASE_OBJS) $(MP_OTHER_OBJS) $(MP_ENCODE_OBJS) \ - $(JPEG_MODULE).o -OBJECTS = ppmtompeg.o $(NONMAIN_OBJS) -MERGE_OBJECTS = ppmtompeg.o2 $(NONMAIN_OBJS) +ADDL_OBJECTS = \ + $(MP_BASE_OBJS) \ + $(MP_OTHER_OBJS) \ + $(MP_ENCODE_OBJS) \ + $(JPEG_MODULE).o \ + +OBJECTS = ppmtompeg.o $(ADDL_OBJECTS) +MERGE_OBJECTS = ppmtompeg.o2 $(ADDL_OBJECTS) MP_INCLUDE = mproto.h mtypes.h huff.h bitio.h MP_MISC = Makefile huff.table parse_huff.pl -BINARIES = ppmtompeg +PORTBINARIES = ppmtompeg +BINARIES = $(PORTBINARIES) MERGEBINARIES = $(BINARIES) SCRIPTS = @@ -84,18 +108,14 @@ else LIBOPTR = endif -ppmtompeg: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ \ - $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \ - $(NETWORKLD) $(MATHLIB) $(LDFLAGS) $(LDLIBS) \ - $(RPATH) $(LADD) - -profile: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ -Bstatic -pg \ - $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \ - $(NETWORKLD) $(MATHLIB) $(LDFLAGS) $(LDLIBS) \ - $(RPATH) $(LADD) +ppmtompeg: $(ADDL_OBJECTS) $(LIBOPT) +ppmtompeg: LDFLAGS_TARGET = \ + $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIBX)) $(NETWORKLD) +profile: $(ADDL_OBJECTS) $(LIBOPT) +profile: LDFLAGS_TARGET = \ + -Bstatic -pg \ + $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIBX)) $(NETWORKLD) ######### # OTHER # diff --git a/converter/ppm/ppmtompeg/gethostname_win32.c b/converter/ppm/ppmtompeg/gethostname_win32.c index 383f4e55..e37fbb37 100644 --- a/converter/ppm/ppmtompeg/gethostname_win32.c +++ b/converter/ppm/ppmtompeg/gethostname_win32.c @@ -94,7 +94,7 @@ get_string_version(push_string_t *str) return FALSE; } - /* Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. */ + /* Call GetNativeSystemInfo if available; GetSystemInfo otherwise. */ pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); -- cgit 1.4.1