diff options
Diffstat (limited to 'converter/other')
47 files changed, 3864 insertions, 2858 deletions
diff --git a/converter/other/Makefile b/converter/other/Makefile index 1a44017f..bbc40a3f 100644 --- a/converter/other/Makefile +++ b/converter/other/Makefile @@ -117,46 +117,38 @@ PORTBINARIES = avstopam bmptopnm fitstopnm \ gemtopnm giftopnm hdifftopam infotopam \ pamtoavs pamtodjvurle pamtofits pamtogif \ pamtohdiff pamtohtmltbl pamtompfont pamtooctaveimg \ - pamtopam pamtopfm pamtopnm pamtouil \ + pamtopam pamtopdbimg pamtopfm pamtopnm pamtosrf pamtouil \ pamtowinicon pamtoxvmini \ - pbmtopgm pfmtopam \ + pbmtopgm pdbimgtopam pfmtopam \ pgmtopbm pgmtoppm ppmtopgm pnmtoddif \ - pnmtopclxl \ + pnmtopclxl pnmtorast \ pnmtosgi pnmtosir pamtotga pnmtoxwd \ - rlatopam sgitopnm sirtopnm sunicontopnm \ + rasttopnm rlatopam sgitopnm sirtopnm srftopam sunicontopnm \ winicontopam xwdtopnm zeisstopnm -BINARIES = \ - $(PORTBINARIES) \ - pamtopdbimg \ - pamtosrf \ - pdbimgtopam \ - pnmtorast \ - rasttopnm \ - srftopam \ - ifneq ($(DONT_HAVE_PROCESS_MGMT),Y) - PORTBINARIES += pstopnm - BINARIES += pnmtops + PORTBINARIES += pstopnm pnmtops endif ifeq ($(HAVE_PNGLIB),Y) - BINARIES += pnmtopng pngtopam pamrgbatopng + PORTBINARIES += pnmtopng pngtopam pamrgbatopng endif ifneq ($(JPEGLIB),NONE) - BINARIES += jpegtopnm pnmtojpeg + PORTBINARIES += jpegtopnm pnmtojpeg endif ifneq ($(TIFF_PREREQ_MISSING),Y) - BINARIES += tifftopnm pamtotiff pnmtotiffcmyk + PORTBINARIES += tifftopnm pamtotiff pnmtotiffcmyk endif ifneq ($(URTLIB),NONE) - BINARIES += rletopnm pnmtorle + PORTBINARIES += rletopnm pnmtorle endif ifneq ($(XML2_LIBS),NONE) - BINARIES += svgtopam + PORTBINARIES += svgtopam endif +BINARIES = $(PORTBINARIES) + MERGEBINARIES = $(BINARIES) EXTRA_OBJECTS = exif.o rast.o ipdb.o srf.o @@ -189,12 +181,14 @@ else LIBOPTR = endif -LIBOPTS_TIFF = $(shell $(LIBOPT) $(NETPBMLIB) \ +LIBOPTS_TIFF = $(shell $(LIBOPT) \ $(LIBOPTR) $(TIFFLIB) $(TIFFLIB_EXTRALIBS)) -tifftopnm pamtotiff pnmtotiffcmyk: %: %.o tiff.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o tiff.o \ - $(LIBOPTS_TIFF) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) +tifftopnm pamtotiff pnmtotiffcmyk: tiff.o +tifftopnm pamtotiff pnmtotiffcmyk: ADDL_OBJECTS = tiff.o +tifftopnm pamtotiff pnmtotiffcmyk: \ + LDFLAGS_TARGET = \ + $(shell $(LIBOPT) $(LIBOPTR) $(TIFFLIB) $(TIFFLIB_EXTRALIBS)) ifneq ($(shell $(TEST_PKGCONFIG_LIBPNG)),) # pkg-config libpng works on this system @@ -209,66 +203,44 @@ else endif endif -pngtopam: %: %.o pngx.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o pngx.o \ - $(shell $(LIBOPT) $(NETPBMLIB)) \ - $(PNGLIB_LIBOPTS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -pnmtopng: %: %.o pngx.o pngtxt.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o pngx.o pngtxt.o \ - $(shell $(LIBOPT) $(NETPBMLIB)) \ - $(PNGLIB_LIBOPTS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -pamrgbatopng: %: %.o pngx.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o pngx.o \ - $(shell $(LIBOPT) $(NETPBMLIB)) $(PNGLIB_LIBOPTS) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -jpegtopnm: %: %.o jpegdatasource.o exif.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $< jpegdatasource.o exif.o \ - $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIB)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -pnmtojpeg: %: %.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o \ - $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIB)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -srftopam pamtosrf: %: %.o srf.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o srf.o \ - $(shell $(LIBOPT) $(NETPBMLIB)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -svgtopam: %: %.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o \ - $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR)) \ - $(XML2_LIBS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) +pngtopam: pngx.o +pngtopam: ADDL_OBJECTS = pngx.o +pngtopam: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS) + +pnmtopng: pngx.o pngtxt.o +pnmtopng: ADDL_OBJECTS = pngx.o pngtxt.o +pnmtopng: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS) + +pamrgbatopng: pngx.o +pamrgbatopng: ADDL_OBJECTS = pngx.o +pamrgbatopng: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS) + +jpegtopnm: jpegdatasource.o exif.o +jpegtopnm: ADDL_OBJECTS = jpegdatasource.o exif.o +jpegtopnm: LDFLAGS_TARGET = $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIB)) + +srftopam pamtosrf: srf.o +srftopam pamtosrf: ADDL_OBJECTS = srf.o + +pnmtojpeg: LDFLAGS_TARGET = $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIB)) + +svgtopam: LDFLAGS_TARGET = $(XML2_LIBS) # If URTLIB is BUNDLED_URTLIB, then we're responsible for building it, which # means it needs to be a dependency: ifeq ($(URTLIB), $(BUNDLED_URTLIB)) - URTLIBDEP = $(URTLIB) +rletopnm pnmtorle: $(URTLIB) endif -rletopnm pnmtorle: %: %.o $(NETPBMLIB) $(URTLIBDEP) $(LIBOPT) - $(LD) -o $@ $@.o \ - $(shell $(LIBOPT) $(URTLIB) $(NETPBMLIB)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -pnmtops: %: %.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o \ - $(shell $(LIBOPT) $(NETPBMLIB) $(PNMTOPS_ZLIB_OPT)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -pnmtorast rasttopnm: %: %.o rast.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o rast.o \ - $(shell $(LIBOPT) $(NETPBMLIB)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -pdbimgtopam pamtopdbimg: %: %.o ipdb.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $@.o ipdb.o \ - $(shell $(LIBOPT) $(NETPBMLIB)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) +rletopnm pnmtorle: LDFLAGS_TARGET = $(shell $(LIBOPT) $(URTLIB)) + +pnmtops: LDFLAGS_TARGET = $(shell $(LIBOPT) $(PNMTOPS_ZLIB_OPT)) + +pnmtorast rasttopnm: rast.o +pnmtorast rasttopnm: ADDL_OBJECTS = rast.o + +pdbimgtopam pamtopdbimg: ipdb.o +pdbimgtopam pamtopdbimg: ADDL_OBJECTS = ipdb.o bmptopnm.o bmptopnm.o2: bmp.h diff --git a/converter/other/cameratopam/Makefile b/converter/other/cameratopam/Makefile index 4470d472..11ca4e1d 100644 --- a/converter/other/cameratopam/Makefile +++ b/converter/other/cameratopam/Makefile @@ -19,22 +19,20 @@ include $(BUILDDIR)/config.mk .PHONY: all all: cameratopam -OBJECTS = util.o identify.o cameratopam.o camera.o foveon.o decode.o \ +ADDL_OBJECTS = util.o identify.o camera.o foveon.o decode.o \ canon.o ljpeg.o dng.o +OBJECTS = cameratopam.o $(ADDL_OBJECTS) + camera.o camera.o2: CFLAGS_TARGET = $(HAVE_JPEG_DEFINE) MERGE_OBJECTS = -BINARIES = cameratopam +PORTBINARIES = cameratopam +BINARIES = $(PORTBINARIES) MERGEBINARIES = SCRIPTS = include $(SRCDIR)/common.mk -cameratopam: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ \ - $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) \ - $(RPATH) $(LADD) - +cameratopam: $(ADDL_OBJECTS) diff --git a/converter/other/exif.c b/converter/other/exif.c index 87d89bd7..1bfe4b2b 100644 --- a/converter/other/exif.c +++ b/converter/other/exif.c @@ -46,22 +46,21 @@ #include "exif.h" -static unsigned char * LastExifRefd; -static unsigned char * DirWithThumbnailPtrs; +static const unsigned char * DirWithThumbnailPtrs; static double FocalplaneXRes; bool HaveXRes; static double FocalplaneUnits; static int ExifImageWidth; -static int MotorolaOrder = 0; typedef struct { unsigned short Tag; const char * Desc; -}TagTable_t; +} TagTable; + /* Describes format descriptor */ -static int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8}; +static int const bytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8}; #define NUM_FORMATS 12 #define FMT_BYTE 1 @@ -120,7 +119,7 @@ static int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8}; #define TAG_THUMBNAIL_OFFSET 0x0201 #define TAG_THUMBNAIL_LENGTH 0x0202 -static TagTable_t const TagTable[] = { +static TagTable const tagTable[] = { { 0x100, "ImageWidth"}, { 0x101, "ImageLength"}, { 0x102, "BitsPerSample"}, @@ -208,498 +207,583 @@ static TagTable_t const TagTable[] = { +typedef enum { NORMAL, MOTOROLA } ByteOrder; + + + +static uint16_t +get16u(const void * const data, + ByteOrder const byteOrder) { /*-------------------------------------------------------------------------- Convert a 16 bit unsigned value from file's native byte order --------------------------------------------------------------------------*/ -static int Get16u(void * Short) -{ - if (MotorolaOrder){ - return (((unsigned char *)Short)[0] << 8) | - ((unsigned char *)Short)[1]; + if (byteOrder == MOTOROLA){ + return (((const unsigned char *)data)[0] << 8) | + ((const unsigned char *)data)[1]; }else{ - return (((unsigned char *)Short)[1] << 8) | - ((unsigned char *)Short)[0]; + return (((const unsigned char *)data)[1] << 8) | + ((const unsigned char *)data)[0]; } } + + +static int32_t +get32s(const void * const data, + ByteOrder const byteOrder) { /*-------------------------------------------------------------------------- Convert a 32 bit signed value from file's native byte order --------------------------------------------------------------------------*/ -static int Get32s(void * Long) -{ - if (MotorolaOrder){ + if (byteOrder == MOTOROLA){ return - ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16) | - (((unsigned char *)Long)[2] << 8 ) | - (((unsigned char *)Long)[3] << 0 ); - }else{ + (((const char *)data)[0] << 24) | + (((const unsigned char *)data)[1] << 16) | + (((const unsigned char *)data)[2] << 8 ) | + (((const unsigned char *)data)[3] << 0 ); + } else { return - ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16) | - (((unsigned char *)Long)[1] << 8 ) | - (((unsigned char *)Long)[0] << 0 ); + (((const char *)data)[3] << 24) | + (((const unsigned char *)data)[2] << 16) | + (((const unsigned char *)data)[1] << 8 ) | + (((const unsigned char *)data)[0] << 0 ); } } + + +static uint32_t +get32u(const void * const data, + ByteOrder const byteOrder) { /*-------------------------------------------------------------------------- Convert a 32 bit unsigned value from file's native byte order --------------------------------------------------------------------------*/ -static unsigned Get32u(void * Long) -{ - return (unsigned)Get32s(Long) & 0xffffffff; + return (uint32_t)get32s(data, byteOrder) & 0xffffffff; } + + +static void +printFormatNumber(FILE * const fileP, + const void * const ValuePtr, + int const Format, + int const ByteCount, + ByteOrder const byteOrder) { /*-------------------------------------------------------------------------- Display a number as one of its many formats --------------------------------------------------------------------------*/ -static void PrintFormatNumber(FILE * const file, - void * const ValuePtr, - int const Format, int const ByteCount) -{ switch(Format){ case FMT_SBYTE: - case FMT_BYTE: printf("%02x\n",*(unsigned char *)ValuePtr); break; - case FMT_USHORT: fprintf(file, "%d\n",Get16u(ValuePtr)); break; + case FMT_BYTE: + fprintf(fileP, "%02x\n", *(unsigned char *)ValuePtr); + break; + case FMT_USHORT: + fprintf(fileP, "%d\n",get16u(ValuePtr, byteOrder)); + break; case FMT_ULONG: - case FMT_SLONG: fprintf(file, "%d\n",Get32s(ValuePtr)); break; + case FMT_SLONG: + fprintf(fileP, "%d\n",get32s(ValuePtr, byteOrder)); + break; case FMT_SSHORT: - fprintf(file, "%hd\n",(signed short)Get16u(ValuePtr)); break; + fprintf(fileP, "%hd\n",(signed short)get16u(ValuePtr, byteOrder)); + break; case FMT_URATIONAL: case FMT_SRATIONAL: - fprintf(file, "%d/%d\n",Get32s(ValuePtr), Get32s(4+(char *)ValuePtr)); + fprintf(fileP, "%d/%d\n",get32s(ValuePtr, byteOrder), + get32s(4+(char *)ValuePtr, byteOrder)); break; case FMT_SINGLE: - fprintf(file, "%f\n",(double)*(float *)ValuePtr); break; - case FMT_DOUBLE: fprintf(file, "%f\n",*(double *)ValuePtr); break; + fprintf(fileP, "%f\n",(double)*(float *)ValuePtr); + break; + case FMT_DOUBLE: + fprintf(fileP, "%f\n",*(double *)ValuePtr); + break; default: - fprintf(file, "Unknown format %d:", Format); + fprintf(fileP, "Unknown format %d:", Format); { - int a; - for (a=0; a < ByteCount && a < 16; ++a) + unsigned int a; + for (a = 0; a < ByteCount && a < 16; ++a) printf("%02x", ((unsigned char *)ValuePtr)[a]); } - fprintf(file, "\n"); + fprintf(fileP, "\n"); } } + +static double +convertAnyFormat(const void * const ValuePtr, + int const Format, + ByteOrder const byteOrder) { /*-------------------------------------------------------------------------- Evaluate number, be it int, rational, or float from directory. --------------------------------------------------------------------------*/ -static double ConvertAnyFormat(void * ValuePtr, int Format) -{ double Value; Value = 0; switch(Format){ - case FMT_SBYTE: Value = *(signed char *)ValuePtr; break; - case FMT_BYTE: Value = *(unsigned char *)ValuePtr; break; - - case FMT_USHORT: Value = Get16u(ValuePtr); break; - case FMT_ULONG: Value = Get32u(ValuePtr); break; - - case FMT_URATIONAL: - case FMT_SRATIONAL: - { - int Num,Den; - Num = Get32s(ValuePtr); - Den = Get32s(4+(char *)ValuePtr); - if (Den == 0){ - Value = 0; - }else{ - Value = (double)Num/Den; - } - break; - } - - case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break; - case FMT_SLONG: Value = Get32s(ValuePtr); break; + case FMT_SBYTE: + Value = *(signed char *)ValuePtr; + break; + case FMT_BYTE: + Value = *(unsigned char *)ValuePtr; + break; + case FMT_USHORT: + Value = get16u(ValuePtr, byteOrder); + break; + case FMT_ULONG: + Value = get32u(ValuePtr, byteOrder); + break; + case FMT_URATIONAL: + case FMT_SRATIONAL: { + int num, den; + num = get32s(ValuePtr, byteOrder); + den = get32s(4+(char *)ValuePtr, byteOrder); + Value = den == 0 ? 0 : (double)(num/den); + } break; + case FMT_SSHORT: + Value = (signed short)get16u(ValuePtr, byteOrder); + break; + case FMT_SLONG: + Value = get32s(ValuePtr, byteOrder); + break; - /* Not sure if this is correct (never seen float used in Exif format) - */ - case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break; - case FMT_DOUBLE: Value = *(double *)ValuePtr; break; + /* Not sure if this is correct (never seen float used in Exif format) */ + case FMT_SINGLE: + Value = (double)*(float *)ValuePtr; + break; + case FMT_DOUBLE: + Value = *(double *)ValuePtr; + break; } return Value; } -/*-------------------------------------------------------------------------- - Process one of the nested EXIF directories. ---------------------------------------------------------------------------*/ -static void -ProcessExifDir(unsigned char * const ExifData, - unsigned int const ExifLength, - unsigned int const DirOffset, - ImageInfo_t * const ImageInfoP, - int const ShowTags, - unsigned char ** const LastExifRefdP) { - - unsigned char * const DirStart = ExifData + DirOffset; - int de; - int a; - int NumDirEntries; - unsigned ThumbnailOffset = 0; - unsigned ThumbnailSize = 0; - - NumDirEntries = Get16u(DirStart); - #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) - { - unsigned char * DirEnd; - DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries); - if (DirEnd+4 > (ExifData+ExifLength)){ - if (DirEnd+2 == ExifData+ExifLength || - DirEnd == ExifData+ExifLength){ - /* Version 1.3 of jhead would truncate a bit too much. - This also caught later on as well. - */ - }else{ - /* Note: Files that had thumbnails trimmed with jhead - 1.3 or earlier might trigger this. + +static void +traceTag(int const tag, + int const format, + const unsigned char * const valuePtr, + unsigned int const byteCount, + ByteOrder const byteOrder) { + + /* Show tag name */ + unsigned int a; + bool found; + for (a = 0, found = false; !found; ++a){ + if (tagTable[a].Tag == 0){ + fprintf(stderr, " Unknown Tag %04x Value = ", tag); + found = true; + } + if (tagTable[a].Tag == tag){ + fprintf(stderr, " %s = ",tagTable[a].Desc); + found = true; + } + } + + /* Show tag value. */ + switch(format){ + + case FMT_UNDEFINED: + /* Undefined is typically an ascii string. */ + + case FMT_STRING: { + /* String arrays printed without function call + (different from int arrays) + */ + bool noPrint; + printf("\""); + for (a = 0, noPrint = false; a < byteCount; ++a){ + if (ISPRINT((valuePtr)[a])){ + fprintf(stderr, "%c", valuePtr[a]); + noPrint = false; + } else { + /* Avoiding indicating too many unprintable characters of + proprietary bits of binary information this program may not + know how to parse. */ - pm_message("Illegal directory entry size"); - return; + if (!noPrint){ + fprintf(stderr, "?"); + noPrint = true; + } } } - if (DirEnd > LastExifRefd) LastExifRefd = DirEnd; + fprintf(stderr, "\"\n"); + } break; + + default: + /* Handle arrays of numbers later (will there ever be?)*/ + printFormatNumber(stderr, valuePtr, format, byteCount, byteOrder); } +} + + + +/* Forward declaration for recursion */ + +static void +processExifDir(const unsigned char * const ExifData, + unsigned int const ExifLength, + unsigned int const DirOffset, + exif_ImageInfo * const imageInfoP, + ByteOrder const byteOrder, + bool const wantTagTrace, + const unsigned char ** const LastExifRefdP); + + +static void +processDirEntry(const unsigned char * const dirEntry, + const unsigned char * const exifData, + unsigned int const exifLength, + ByteOrder const byteOrder, + bool const wantTagTrace, + exif_ImageInfo * const imageInfoP, + unsigned int * const thumbnailOffsetP, + unsigned int * const thumbnailSizeP, + bool * const haveThumbnailP, + const unsigned char ** const lastExifRefdP) { + + int const tag = get16u(&dirEntry[0], byteOrder); + int const format = get16u(&dirEntry[2], byteOrder); + int const components = get32u(&dirEntry[4], byteOrder); + + const unsigned char * valuePtr; + /* This actually can point to a variety of things; it must be cast to + other types when used. But we use it as a byte-by-byte cursor, so + we declare it as a pointer to a generic byte here. + */ + unsigned int byteCount; - if (ShowTags){ - pm_message("Directory with %d entries",NumDirEntries); + if ((format-1) >= NUM_FORMATS) { + /* (-1) catches illegal zero case as unsigned underflows + to positive large. + */ + pm_message("Illegal number format %d for tag %04x", format, tag); + return; + } + + byteCount = components * bytesPerFormat[format]; + + if (byteCount > 4){ + unsigned const offsetVal = get32u(&dirEntry[8], byteOrder); + /* If its bigger than 4 bytes, the dir entry contains an offset.*/ + if (offsetVal + byteCount > exifLength){ + /* Bogus pointer offset and / or bytecount value */ + pm_message("Illegal pointer offset value in EXIF " + "for tag %04x. " + "Offset %d bytes %d ExifLen %d\n", + tag, offsetVal, byteCount, exifLength); + return; + } + valuePtr = &exifData[offsetVal]; + } else { + /* 4 bytes or less and value is in the dir entry itself */ + valuePtr = &dirEntry[8]; } - for (de=0;de<NumDirEntries;de++){ - int Tag, Format, Components; - unsigned char * ValuePtr; - /* This actually can point to a variety of things; it must - be cast to other types when used. But we use it as a - byte-by-byte cursor, so we declare it as a pointer to a - generic byte here. - */ - int ByteCount; - unsigned char * DirEntry; - DirEntry = DIR_ENTRY_ADDR(DirStart, de); + if (*lastExifRefdP < valuePtr + byteCount){ + /* Keep track of last byte in the exif header that was actually + referenced. That way, we know where the discardable thumbnail data + begins. + */ + *lastExifRefdP = valuePtr + byteCount; + } - Tag = Get16u(DirEntry); - Format = Get16u(DirEntry+2); - Components = Get32u(DirEntry+4); + if (wantTagTrace) + traceTag(tag, format, valuePtr, byteCount, byteOrder); - if ((Format-1) >= NUM_FORMATS) { - /* (-1) catches illegal zero case as unsigned underflows - to positive large. - */ - pm_message("Illegal number format %d for tag %04x", Format, Tag); - continue; + *haveThumbnailP = (tag == TAG_THUMBNAIL_OFFSET); + + /* Extract useful components of tag */ + switch (tag){ + + case TAG_MAKE: + STRSCPY(imageInfoP->CameraMake, (const char*)valuePtr); + break; + + case TAG_MODEL: + STRSCPY(imageInfoP->CameraModel, (const char*)valuePtr); + break; + + case TAG_XRESOLUTION: + imageInfoP->XResolution = + convertAnyFormat(valuePtr, format, byteOrder); + break; + + case TAG_YRESOLUTION: + imageInfoP->YResolution = + convertAnyFormat(valuePtr, format, byteOrder); + break; + + case TAG_DATETIME_ORIGINAL: + STRSCPY(imageInfoP->DateTime, (const char*)valuePtr); + imageInfoP->DatePointer = (const char*)valuePtr; + break; + + case TAG_USERCOMMENT: { + /* Olympus has this padded with trailing spaces. We stop the copy + where those start. + */ + const char * const value = (const char *)valuePtr; + + unsigned int cursor; + unsigned int outCursor; + unsigned int end; + + for (end = byteCount; end > 0 && value[end] == ' '; --end); + + /* Skip "ASCII" if it is there */ + if (end >= 5 && MEMEQ(value, "ASCII", 5)) + cursor = 5; + else + cursor = 0; + + /* Skip consecutive blanks and NULs */ + + for (; + cursor < byteCount && + (value[cursor] == '\0' || value[cursor] == ' '); + ++cursor); + + /* Copy the rest as the comment */ + + for (outCursor = 0; + cursor < end && outCursor < MAX_COMMENT-1; + ++cursor) + imageInfoP->Comments[outCursor++] = value[cursor]; + + imageInfoP->Comments[outCursor++] = '\0'; + } break; + + case TAG_FNUMBER: + /* Simplest way of expressing aperture, so I trust it the most. + (overwrite previously computd value if there is one) + */ + imageInfoP->ApertureFNumber = + (float)convertAnyFormat(valuePtr, format, byteOrder); + break; + + case TAG_APERTURE: + case TAG_MAXAPERTURE: + /* More relevant info always comes earlier, so only use this field if + we don't have appropriate aperture information yet. + */ + if (imageInfoP->ApertureFNumber == 0){ + imageInfoP->ApertureFNumber = (float) + exp(convertAnyFormat(valuePtr, format, byteOrder) + * log(2) * 0.5); } - - ByteCount = Components * BytesPerFormat[Format]; - - if (ByteCount > 4){ - unsigned OffsetVal; - OffsetVal = Get32u(DirEntry+8); - /* If its bigger than 4 bytes, the dir entry contains an offset.*/ - if (OffsetVal+ByteCount > ExifLength){ - /* Bogus pointer offset and / or bytecount value */ - pm_message("Illegal pointer offset value in EXIF " - "for tag %04x. " - "Offset %d bytes %d ExifLen %d\n", - Tag, OffsetVal, ByteCount, ExifLength); - continue; - } - ValuePtr = ExifData+OffsetVal; + break; + + case TAG_FOCALLENGTH: + /* Nice digital cameras actually save the focal length + as a function of how farthey are zoomed in. + */ + + imageInfoP->FocalLength = + (float)convertAnyFormat(valuePtr, format, byteOrder); + break; + + case TAG_SUBJECT_DISTANCE: + /* Inidcates the distacne the autofocus camera is focused to. + Tends to be less accurate as distance increases. + */ + imageInfoP->Distance = + (float)convertAnyFormat(valuePtr, format, byteOrder); + break; + + case TAG_EXPOSURETIME: + /* Simplest way of expressing exposure time, so I + trust it most. (overwrite previously computd value + if there is one) + */ + imageInfoP->ExposureTime = + (float)convertAnyFormat(valuePtr, format, byteOrder); + break; + + case TAG_SHUTTERSPEED: + /* More complicated way of expressing exposure time, + so only use this value if we don't already have it + from somewhere else. + */ + if (imageInfoP->ExposureTime == 0){ + imageInfoP->ExposureTime = (float) + (1/exp(convertAnyFormat(valuePtr, format, byteOrder) + * log(2))); + } + break; + + case TAG_FLASH: + if ((int)convertAnyFormat(valuePtr, format, byteOrder) & 0x7){ + imageInfoP->FlashUsed = TRUE; }else{ - /* 4 bytes or less and value is in the dir entry itself */ - ValuePtr = DirEntry+8; + imageInfoP->FlashUsed = FALSE; } + break; - if (*LastExifRefdP < ValuePtr+ByteCount){ - /* Keep track of last byte in the exif header that was - actually referenced. That way, we know where the - discardable thumbnail data begins. - */ - *LastExifRefdP = ValuePtr+ByteCount; + case TAG_ORIENTATION: + imageInfoP->Orientation = + (int)convertAnyFormat(valuePtr, format, byteOrder); + if (imageInfoP->Orientation < 1 || + imageInfoP->Orientation > 8){ + pm_message("Undefined rotation value %d", + imageInfoP->Orientation); + imageInfoP->Orientation = 0; } + break; - if (ShowTags){ - /* Show tag name */ - for (a=0;;a++){ - if (TagTable[a].Tag == 0){ - fprintf(stderr, " Unknown Tag %04x Value = ", Tag); - break; - } - if (TagTable[a].Tag == Tag){ - fprintf(stderr, " %s = ",TagTable[a].Desc); - break; - } - } + case TAG_EXIF_IMAGELENGTH: + case TAG_EXIF_IMAGEWIDTH: + /* Use largest of height and width to deal with images + that have been rotated to portrait format. + */ + ExifImageWidth = + MIN(ExifImageWidth, + (int)convertAnyFormat(valuePtr, format, byteOrder)); + break; - /* Show tag value. */ - switch(Format){ - - case FMT_UNDEFINED: - /* Undefined is typically an ascii string. */ - - case FMT_STRING: - /* String arrays printed without function call - (different from int arrays) - */ - { - int NoPrint = 0; - printf("\""); - for (a=0;a<ByteCount;a++){ - if (ISPRINT((ValuePtr)[a])){ - fprintf(stderr, "%c", (ValuePtr)[a]); - NoPrint = 0; - }else{ - - /* Avoiding indicating too many - unprintable characters of proprietary - bits of binary information this - program may not know how to parse. - */ - if (!NoPrint){ - fprintf(stderr, "?"); - NoPrint = 1; - } - } - } - fprintf(stderr, "\"\n"); - } - break; + case TAG_FOCALPLANEXRES: + HaveXRes = TRUE; + FocalplaneXRes = convertAnyFormat(valuePtr, format, byteOrder); + break; - default: - /* Handle arrays of numbers later (will there ever be?)*/ - PrintFormatNumber(stderr, ValuePtr, Format, ByteCount); - } + case TAG_FOCALPLANEUNITS: + switch((int)convertAnyFormat(valuePtr, format, byteOrder)){ + case 1: FocalplaneUnits = 25.4; break; /* 1 inch */ + case 2: + /* According to the information I was using, 2 + means meters. But looking at the Cannon + powershot's files, inches is the only + sensible value. + */ + FocalplaneUnits = 25.4; + break; + + case 3: FocalplaneUnits = 10; break; /* 1 centimeter*/ + case 4: FocalplaneUnits = 1; break; /* 1 millimeter*/ + case 5: FocalplaneUnits = .001; break; /* 1 micrometer*/ } + break; - /* Extract useful components of tag */ - switch(Tag){ - - case TAG_MAKE: - STRSCPY(ImageInfoP->CameraMake, (char*)ValuePtr); - break; - - case TAG_MODEL: - STRSCPY(ImageInfoP->CameraModel, (char*)ValuePtr); - break; - - case TAG_XRESOLUTION: - ImageInfoP->XResolution = - ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_YRESOLUTION: - ImageInfoP->YResolution = - ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_DATETIME_ORIGINAL: - STRSCPY(ImageInfoP->DateTime, (char*)ValuePtr); - ImageInfoP->DatePointer = (char*)ValuePtr; - break; - - case TAG_USERCOMMENT: - /* Olympus has this padded with trailing spaces. - Remove these first. - */ - for (a=ByteCount;;){ - a--; - if (((char*)ValuePtr)[a] == ' '){ - ((char*)ValuePtr)[a] = '\0'; - }else{ - break; - } - if (a == 0) break; - } + /* Remaining cases contributed by: Volker C. Schoech + (schoech@gmx.de) + */ - /* Copy the comment */ - if (memcmp(ValuePtr, "ASCII",5) == 0){ - for (a=5;a<10;a++){ - char c; - c = ((char*)ValuePtr)[a]; - if (c != '\0' && c != ' '){ - strncpy(ImageInfoP->Comments, (char*)ValuePtr+a, - 199); - break; - } - } - - }else{ - strncpy(ImageInfoP->Comments, (char*)ValuePtr, 199); - } - break; - - case TAG_FNUMBER: - /* Simplest way of expressing aperture, so I trust it the most. - (overwrite previously computd value if there is one) - */ - ImageInfoP->ApertureFNumber = - (float)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_APERTURE: - case TAG_MAXAPERTURE: - /* More relevant info always comes earlier, so only - use this field if we don't have appropriate aperture - information yet. - */ - if (ImageInfoP->ApertureFNumber == 0){ - ImageInfoP->ApertureFNumber = (float) - exp(ConvertAnyFormat(ValuePtr, Format)*log(2)*0.5); - } - break; + case TAG_EXPOSURE_BIAS: + imageInfoP->ExposureBias = + (float) convertAnyFormat(valuePtr, format, byteOrder); + break; - case TAG_FOCALLENGTH: - /* Nice digital cameras actually save the focal length - as a function of how farthey are zoomed in. - */ + case TAG_WHITEBALANCE: + imageInfoP->Whitebalance = + (int)convertAnyFormat(valuePtr, format, byteOrder); + break; - ImageInfoP->FocalLength = - (float)ConvertAnyFormat(ValuePtr, Format); - break; + case TAG_METERING_MODE: + imageInfoP->MeteringMode = + (int)convertAnyFormat(valuePtr, format, byteOrder); + break; - case TAG_SUBJECT_DISTANCE: - /* Inidcates the distacne the autofocus camera is focused to. - Tends to be less accurate as distance increases. - */ - ImageInfoP->Distance = - (float)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_EXPOSURETIME: - /* Simplest way of expressing exposure time, so I - trust it most. (overwrite previously computd value - if there is one) - */ - ImageInfoP->ExposureTime = - (float)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_SHUTTERSPEED: - /* More complicated way of expressing exposure time, - so only use this value if we don't already have it - from somewhere else. - */ - if (ImageInfoP->ExposureTime == 0){ - ImageInfoP->ExposureTime = (float) - (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2))); - } - break; + case TAG_EXPOSURE_PROGRAM: + imageInfoP->ExposureProgram = + (int)convertAnyFormat(valuePtr, format, byteOrder); + break; - case TAG_FLASH: - if ((int)ConvertAnyFormat(ValuePtr, Format) & 7){ - ImageInfoP->FlashUsed = TRUE; - }else{ - ImageInfoP->FlashUsed = FALSE; - } - break; - - case TAG_ORIENTATION: - ImageInfoP->Orientation = - (int)ConvertAnyFormat(ValuePtr, Format); - if (ImageInfoP->Orientation < 1 || - ImageInfoP->Orientation > 8){ - pm_message("Undefined rotation value %d", - ImageInfoP->Orientation); - ImageInfoP->Orientation = 0; - } - break; + case TAG_ISO_EQUIVALENT: + imageInfoP->ISOequivalent = + (int)convertAnyFormat(valuePtr, format, byteOrder); + if ( imageInfoP->ISOequivalent < 50 ) + imageInfoP->ISOequivalent *= 200; + break; - case TAG_EXIF_IMAGELENGTH: - case TAG_EXIF_IMAGEWIDTH: - /* Use largest of height and width to deal with images - that have been rotated to portrait format. - */ - a = (int)ConvertAnyFormat(ValuePtr, Format); - if (ExifImageWidth < a) ExifImageWidth = a; - break; - - case TAG_FOCALPLANEXRES: - HaveXRes = TRUE; - FocalplaneXRes = ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_FOCALPLANEUNITS: - switch((int)ConvertAnyFormat(ValuePtr, Format)){ - case 1: FocalplaneUnits = 25.4; break; /* 1 inch */ - case 2: - /* According to the information I was using, 2 - means meters. But looking at the Cannon - powershot's files, inches is the only - sensible value. - */ - FocalplaneUnits = 25.4; - break; + case TAG_COMPRESSION_LEVEL: + imageInfoP->CompressionLevel = + (int)convertAnyFormat(valuePtr, format, byteOrder); + break; - case 3: FocalplaneUnits = 10; break; /* 1 centimeter*/ - case 4: FocalplaneUnits = 1; break; /* 1 millimeter*/ - case 5: FocalplaneUnits = .001; break; /* 1 micrometer*/ - } - break; + case TAG_THUMBNAIL_OFFSET: + *thumbnailOffsetP = (unsigned int) + convertAnyFormat(valuePtr, format, byteOrder); + break; - /* Remaining cases contributed by: Volker C. Schoech - (schoech@gmx.de) - */ + case TAG_THUMBNAIL_LENGTH: + *thumbnailSizeP = (unsigned int) + convertAnyFormat(valuePtr, format, byteOrder); + break; - case TAG_EXPOSURE_BIAS: - ImageInfoP->ExposureBias = - (float) ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_WHITEBALANCE: - ImageInfoP->Whitebalance = - (int)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_METERING_MODE: - ImageInfoP->MeteringMode = - (int)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_EXPOSURE_PROGRAM: - ImageInfoP->ExposureProgram = - (int)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_ISO_EQUIVALENT: - ImageInfoP->ISOequivalent = - (int)ConvertAnyFormat(ValuePtr, Format); - if ( ImageInfoP->ISOequivalent < 50 ) - ImageInfoP->ISOequivalent *= 200; - break; - - case TAG_COMPRESSION_LEVEL: - ImageInfoP->CompressionLevel = - (int)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_THUMBNAIL_OFFSET: - ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format); - DirWithThumbnailPtrs = DirStart; - break; - - case TAG_THUMBNAIL_LENGTH: - ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format); - break; - - case TAG_EXIF_OFFSET: - case TAG_INTEROP_OFFSET: - { - unsigned int const SubdirOffset = Get32u(ValuePtr); - if (SubdirOffset >= ExifLength) - pm_message("Illegal exif or interop offset " - "directory link. Offset is %u, " - "but Exif data is only %u bytes.", - SubdirOffset, ExifLength); - else - ProcessExifDir(ExifData, ExifLength, SubdirOffset, - ImageInfoP, ShowTags, LastExifRefdP); - continue; - } - } + case TAG_EXIF_OFFSET: + case TAG_INTEROP_OFFSET: { + unsigned int const subdirOffset = get32u(valuePtr, byteOrder); + if (subdirOffset >= exifLength) + pm_message("Illegal exif or interop offset " + "directory link. Offset is %u, " + "but Exif data is only %u bytes.", + subdirOffset, exifLength); + else + processExifDir(exifData, exifLength, subdirOffset, + imageInfoP, byteOrder, wantTagTrace, + lastExifRefdP); + } break; + } +} + + + +static void +processExifDir(const unsigned char * const exifData, + unsigned int const exifLength, + unsigned int const dirOffset, + exif_ImageInfo * const imageInfoP, + ByteOrder const byteOrder, + bool const wantTagTrace, + const unsigned char ** const lastExifRefdP) { +/*-------------------------------------------------------------------------- + Process one of the nested EXIF directories. +--------------------------------------------------------------------------*/ + const unsigned char * const dirStart = exifData + dirOffset; + unsigned int const numDirEntries = get16u(&dirStart[0], byteOrder); + unsigned int de; + bool haveThumbnail; + unsigned int thumbnailOffset; + unsigned int thumbnailSize; + + #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) + { + const unsigned char * const dirEnd = + DIR_ENTRY_ADDR(dirStart, numDirEntries); + if (dirEnd + 4 > (exifData + exifLength)){ + if (dirEnd + 2 == exifData + exifLength || + dirEnd == exifData + exifLength){ + /* Version 1.3 of jhead would truncate a bit too much. + This also caught later on as well. + */ + }else{ + /* Note: Files that had thumbnails trimmed with jhead + 1.3 or earlier might trigger this. + */ + pm_message("Illegal directory entry size"); + return; + } + } + *lastExifRefdP = MAX(*lastExifRefdP, dirEnd); } + if (wantTagTrace) + pm_message("Directory with %d entries", numDirEntries); + + haveThumbnail = false; /* initial value */ + thumbnailOffset = 0; /* initial value */ + thumbnailSize = 0; /* initial value */ + + for (de = 0; de < numDirEntries; ++de) + processDirEntry(DIR_ENTRY_ADDR(dirStart, de), exifData, exifLength, + byteOrder, wantTagTrace, imageInfoP, + &thumbnailOffset, &thumbnailSize, &haveThumbnail, + lastExifRefdP); + + if (haveThumbnail) + DirWithThumbnailPtrs = dirStart; { /* In addition to linking to subdirectories via exif tags, @@ -707,28 +791,30 @@ ProcessExifDir(unsigned char * const ExifData, of each directory. This has got to be the result of a committee! */ - if (DIR_ENTRY_ADDR(DirStart, NumDirEntries) + 4 <= - ExifData+ExifLength){ - unsigned int const SubdirOffset = - Get32u(DirStart+2+12*NumDirEntries); - if (SubdirOffset){ - unsigned char * const SubdirStart = ExifData + SubdirOffset; - if (SubdirStart > ExifData+ExifLength){ - if (SubdirStart < ExifData+ExifLength+20){ + if (DIR_ENTRY_ADDR(dirStart, numDirEntries) + 4 <= + exifData + exifLength){ + unsigned int const subdirOffset = + get32u(dirStart + 2 + 12*numDirEntries, byteOrder); + if (subdirOffset){ + const unsigned char * const subdirStart = + exifData + subdirOffset; + if (subdirStart > exifData + exifLength){ + if (subdirStart < exifData + exifLength + 20){ /* Jhead 1.3 or earlier would crop the whole directory! As Jhead produces this form of format incorrectness, I'll just let it pass silently. */ - if (ShowTags) + if (wantTagTrace) printf("Thumbnail removed with " "Jhead 1.3 or earlier\n"); }else{ pm_message("Illegal subdirectory link"); } }else{ - if (SubdirOffset <= ExifLength) - ProcessExifDir(ExifData, ExifLength, SubdirOffset, - ImageInfoP, ShowTags, LastExifRefdP); + if (subdirOffset <= exifLength) + processExifDir(exifData, exifLength, subdirOffset, + imageInfoP, byteOrder, wantTagTrace, + lastExifRefdP); } } }else{ @@ -736,14 +822,14 @@ ProcessExifDir(unsigned char * const ExifData, } } - if (ThumbnailSize && ThumbnailOffset){ - if (ThumbnailSize + ThumbnailOffset <= ExifLength){ + if (thumbnailSize && thumbnailOffset){ + if (thumbnailSize + thumbnailOffset <= exifLength){ /* The thumbnail pointer appears to be valid. Store it. */ - ImageInfoP->ThumbnailPointer = ExifData + ThumbnailOffset; - ImageInfoP->ThumbnailSize = ThumbnailSize; + imageInfoP->ThumbnailPointer = exifData + thumbnailOffset; + imageInfoP->ThumbnailSize = thumbnailSize; - if (ShowTags){ - fprintf(stderr, "Thumbnail size: %d bytes\n",ThumbnailSize); + if (wantTagTrace){ + fprintf(stderr, "Thumbnail size: %u bytes\n", thumbnailSize); } } } @@ -752,46 +838,46 @@ ProcessExifDir(unsigned char * const ExifData, void -process_EXIF(unsigned char * const ExifData, - unsigned int const length, - ImageInfo_t * const ImageInfoP, - int const ShowTags, - const char ** const errorP) { +exif_parse(const unsigned char * const exifData, + unsigned int const length, + exif_ImageInfo * const imageInfoP, + bool const wantTagTrace, + const char ** const errorP) { /*-------------------------------------------------------------------------- Interpret an EXIF APP1 marker - 'ExifData' is the actual Exif data; it does not include the + 'exifData' is the actual Exif data; it does not include the "Exif" identifier and length field that often prefix Exif data. 'length' is the length of the Exif section. --------------------------------------------------------------------------*/ + ByteOrder byteOrder; int FirstOffset; - unsigned char * LastExifRefd; + const unsigned char * lastExifRefd; *errorP = NULL; /* initial assumption */ - if (ShowTags){ + if (wantTagTrace) fprintf(stderr, "Exif header %d bytes long\n",length); - } - if (memcmp(ExifData+0,"II",2) == 0) { - if (ShowTags) + if (MEMEQ(exifData + 0, "II" , 2)) { + if (wantTagTrace) fprintf(stderr, "Exif header in Intel order\n"); - MotorolaOrder = 0; + byteOrder = NORMAL; } else { - if (memcmp(ExifData+0, "MM", 2) == 0) { - if (ShowTags) + if (MEMEQ(exifData + 0, "MM", 2)) { + if (wantTagTrace) fprintf(stderr, "Exif header in Motorola order\n"); - MotorolaOrder = 1; + byteOrder = MOTOROLA; } else { pm_asprintf(errorP, "Invalid alignment marker in Exif " "data. First two bytes are '%c%c' (0x%02x%02x) " "instead of 'II' or 'MM'.", - ExifData[0], ExifData[1], ExifData[0], ExifData[1]); + exifData[0], exifData[1], exifData[0], exifData[1]); } } if (!*errorP) { - unsigned short const start = Get16u(ExifData + 2); + unsigned short const start = get16u(exifData + 2, byteOrder); /* Check the next value for correctness. */ if (start != 0x002a){ pm_asprintf(errorP, "Invalid Exif header start. " @@ -801,7 +887,7 @@ process_EXIF(unsigned char * const ExifData, } } if (!*errorP) { - FirstOffset = Get32u(ExifData + 4); + FirstOffset = get32u(exifData + 4, byteOrder); if (FirstOffset < 8 || FirstOffset > 16){ /* I used to ensure this was set to 8 (website I used indicated its 8) but PENTAX Optio 230 has it set @@ -810,51 +896,54 @@ process_EXIF(unsigned char * const ExifData, pm_message("Suspicious offset of first IFD value in Exif header"); } - ImageInfoP->Comments[0] = '\0'; /* Initial value - null string */ + imageInfoP->Comments[0] = '\0'; /* Initial value - null string */ HaveXRes = FALSE; /* Initial assumption */ FocalplaneUnits = 0; ExifImageWidth = 0; - LastExifRefd = ExifData; + lastExifRefd = exifData; DirWithThumbnailPtrs = NULL; - ProcessExifDir(ExifData, length, FirstOffset, - ImageInfoP, ShowTags, &LastExifRefd); + processExifDir(exifData, length, FirstOffset, + imageInfoP, byteOrder, wantTagTrace, &lastExifRefd); /* Compute the CCD width, in millimeters. */ if (HaveXRes){ - ImageInfoP->HaveCCDWidth = 1; - ImageInfoP->CCDWidth = + imageInfoP->HaveCCDWidth = 1; + imageInfoP->CCDWidth = (float)(ExifImageWidth * FocalplaneUnits / FocalplaneXRes); } else - ImageInfoP->HaveCCDWidth = 0; + imageInfoP->HaveCCDWidth = 0; - if (ShowTags){ + if (wantTagTrace){ fprintf(stderr, "Non-settings part of Exif header: %lu bytes\n", - (unsigned long)(ExifData+length-LastExifRefd)); + (unsigned long)(exifData + length - lastExifRefd)); } } } + + +void +exif_showImageInfo(const exif_ImageInfo * const imageInfoP, + FILE * const fileP) { /*-------------------------------------------------------------------------- Show the collected image info, displaying camera F-stop and shutter speed in a consistent and legible fashion. --------------------------------------------------------------------------*/ -void -ShowImageInfo(ImageInfo_t * const ImageInfoP) -{ - if (ImageInfoP->CameraMake[0]){ - fprintf(stderr, "Camera make : %s\n",ImageInfoP->CameraMake); - fprintf(stderr, "Camera model : %s\n",ImageInfoP->CameraModel); + if (imageInfoP->CameraMake[0]) { + fprintf(fileP, "Camera make : %s\n", imageInfoP->CameraMake); + fprintf(fileP, "Camera model : %s\n", imageInfoP->CameraModel); } - if (ImageInfoP->DateTime[0]){ - fprintf(stderr, "Date/Time : %s\n",ImageInfoP->DateTime); - } - fprintf(stderr, "Resolution : %f x %f\n", - ImageInfoP->XResolution, ImageInfoP->YResolution); - if (ImageInfoP->Orientation > 1){ + if (imageInfoP->DateTime[0]) + fprintf(fileP, "Date/Time : %s\n", imageInfoP->DateTime); + + fprintf(fileP, "Resolution : %f x %f\n", + imageInfoP->XResolution, imageInfoP->YResolution); + + if (imageInfoP->Orientation > 1) { /* Only print orientation if one was supplied, and if its not 1 (normal orientation) @@ -891,154 +980,144 @@ ShowImageInfo(ImageInfo_t * const ImageInfoP) "rotate 270", /* rotate 270 to right it. */ }; - fprintf(stderr, "Orientation : %s\n", - OrientTab[ImageInfoP->Orientation]); + fprintf(fileP, "Orientation : %s\n", + OrientTab[imageInfoP->Orientation]); } - if (ImageInfoP->IsColor == 0){ - fprintf(stderr, "Color/bw : Black and white\n"); - } - if (ImageInfoP->FlashUsed >= 0){ - fprintf(stderr, "Flash used : %s\n", - ImageInfoP->FlashUsed ? "Yes" :"No"); - } - if (ImageInfoP->FocalLength){ - fprintf(stderr, "Focal length : %4.1fmm", - (double)ImageInfoP->FocalLength); - if (ImageInfoP->HaveCCDWidth){ - fprintf(stderr, " (35mm equivalent: %dmm)", + if (imageInfoP->IsColor == 0) + fprintf(fileP, "Color/bw : Black and white\n"); + + if (imageInfoP->FlashUsed >= 0) + fprintf(fileP, "Flash used : %s\n", + imageInfoP->FlashUsed ? "Yes" :"No"); + + if (imageInfoP->FocalLength) { + fprintf(fileP, "Focal length : %4.1fmm", + (double)imageInfoP->FocalLength); + if (imageInfoP->HaveCCDWidth){ + fprintf(fileP, " (35mm equivalent: %dmm)", (int) - (ImageInfoP->FocalLength/ImageInfoP->CCDWidth*36 + 0.5)); + (imageInfoP->FocalLength/imageInfoP->CCDWidth*36 + 0.5)); } - fprintf(stderr, "\n"); + fprintf(fileP, "\n"); } - if (ImageInfoP->HaveCCDWidth){ - fprintf(stderr, "CCD width : %2.4fmm\n", - (double)ImageInfoP->CCDWidth); - } + if (imageInfoP->HaveCCDWidth) + fprintf(fileP, "CCD width : %2.4fmm\n", + (double)imageInfoP->CCDWidth); - if (ImageInfoP->ExposureTime){ - if (ImageInfoP->ExposureTime < 0.010){ - fprintf(stderr, + if (imageInfoP->ExposureTime) { + if (imageInfoP->ExposureTime < 0.010){ + fprintf(fileP, "Exposure time: %6.4f s ", - (double)ImageInfoP->ExposureTime); + (double)imageInfoP->ExposureTime); }else{ - fprintf(stderr, + fprintf(fileP, "Exposure time: %5.3f s ", - (double)ImageInfoP->ExposureTime); + (double)imageInfoP->ExposureTime); } - if (ImageInfoP->ExposureTime <= 0.5){ - fprintf(stderr, " (1/%d)",(int)(0.5 + 1/ImageInfoP->ExposureTime)); + if (imageInfoP->ExposureTime <= 0.5){ + fprintf(fileP, " (1/%d)",(int)(0.5 + 1/imageInfoP->ExposureTime)); } - fprintf(stderr, "\n"); + fprintf(fileP, "\n"); } - if (ImageInfoP->ApertureFNumber){ - fprintf(stderr, "Aperture : f/%3.1f\n", - (double)ImageInfoP->ApertureFNumber); + if (imageInfoP->ApertureFNumber){ + fprintf(fileP, "Aperture : f/%3.1f\n", + (double)imageInfoP->ApertureFNumber); } - if (ImageInfoP->Distance){ - if (ImageInfoP->Distance < 0){ - fprintf(stderr, "Focus dist. : Infinite\n"); + if (imageInfoP->Distance){ + if (imageInfoP->Distance < 0){ + fprintf(fileP, "Focus dist. : Infinite\n"); }else{ - fprintf(stderr, "Focus dist. :%5.2fm\n", - (double)ImageInfoP->Distance); + fprintf(fileP, "Focus dist. :%5.2fm\n", + (double)imageInfoP->Distance); } } - - - - - if (ImageInfoP->ISOequivalent){ /* 05-jan-2001 vcs */ - fprintf(stderr, "ISO equiv. : %2d\n",(int)ImageInfoP->ISOequivalent); + if (imageInfoP->ISOequivalent){ /* 05-jan-2001 vcs */ + fprintf(fileP, "ISO equiv. : %2d\n",(int)imageInfoP->ISOequivalent); } - if (ImageInfoP->ExposureBias){ /* 05-jan-2001 vcs */ - fprintf(stderr, "Exposure bias:%4.2f\n", - (double)ImageInfoP->ExposureBias); + if (imageInfoP->ExposureBias){ /* 05-jan-2001 vcs */ + fprintf(fileP, "Exposure bias:%4.2f\n", + (double)imageInfoP->ExposureBias); } - if (ImageInfoP->Whitebalance){ /* 05-jan-2001 vcs */ - switch(ImageInfoP->Whitebalance) { + if (imageInfoP->Whitebalance){ /* 05-jan-2001 vcs */ + switch(imageInfoP->Whitebalance) { case 1: - fprintf(stderr, "Whitebalance : sunny\n"); + fprintf(fileP, "Whitebalance : sunny\n"); break; case 2: - fprintf(stderr, "Whitebalance : fluorescent\n"); + fprintf(fileP, "Whitebalance : fluorescent\n"); break; case 3: - fprintf(stderr, "Whitebalance : incandescent\n"); + fprintf(fileP, "Whitebalance : incandescent\n"); break; default: - fprintf(stderr, "Whitebalance : cloudy\n"); + fprintf(fileP, "Whitebalance : cloudy\n"); } } - if (ImageInfoP->MeteringMode){ /* 05-jan-2001 vcs */ - switch(ImageInfoP->MeteringMode) { + if (imageInfoP->MeteringMode){ /* 05-jan-2001 vcs */ + switch(imageInfoP->MeteringMode) { case 2: - fprintf(stderr, "Metering Mode: center weight\n"); + fprintf(fileP, "Metering Mode: center weight\n"); break; case 3: - fprintf(stderr, "Metering Mode: spot\n"); + fprintf(fileP, "Metering Mode: spot\n"); break; case 5: - fprintf(stderr, "Metering Mode: matrix\n"); + fprintf(fileP, "Metering Mode: matrix\n"); break; } } - if (ImageInfoP->ExposureProgram){ /* 05-jan-2001 vcs */ - switch(ImageInfoP->ExposureProgram) { + if (imageInfoP->ExposureProgram){ /* 05-jan-2001 vcs */ + switch(imageInfoP->ExposureProgram) { case 2: - fprintf(stderr, "Exposure : program (auto)\n"); + fprintf(fileP, "Exposure : program (auto)\n"); break; case 3: - fprintf(stderr, "Exposure : aperture priority (semi-auto)\n"); + fprintf(fileP, "Exposure : aperture priority (semi-auto)\n"); break; case 4: - fprintf(stderr, "Exposure : shutter priority (semi-auto)\n"); + fprintf(fileP, "Exposure : shutter priority (semi-auto)\n"); break; } } - if (ImageInfoP->CompressionLevel){ /* 05-jan-2001 vcs */ - switch(ImageInfoP->CompressionLevel) { + if (imageInfoP->CompressionLevel){ /* 05-jan-2001 vcs */ + switch(imageInfoP->CompressionLevel) { case 1: - fprintf(stderr, "Jpeg Quality : basic\n"); + fprintf(fileP, "Jpeg Quality : basic\n"); break; case 2: - fprintf(stderr, "Jpeg Quality : normal\n"); + fprintf(fileP, "Jpeg Quality : normal\n"); break; case 4: - fprintf(stderr, "Jpeg Quality : fine\n"); + fprintf(fileP, "Jpeg Quality : fine\n"); break; } } - - /* Print the comment. Print 'Comment:' for each new line of comment. */ - if (ImageInfoP->Comments[0]){ - int a,c; - fprintf(stderr, "Comment : "); - for (a=0;a<MAX_COMMENT;a++){ - c = ImageInfoP->Comments[a]; - if (c == '\0') break; + if (imageInfoP->Comments[0]) { + unsigned int a; + + fprintf(fileP, "Comment : "); + + for (a = 0; a < MAX_COMMENT && imageInfoP->Comments[a]; ++a) { + char const c = imageInfoP->Comments[a]; if (c == '\n'){ /* Do not start a new line if the string ends with a cr */ - if (ImageInfoP->Comments[a+1] != '\0'){ - fprintf(stderr, "\nComment : "); - }else{ - fprintf(stderr, "\n"); - } - }else{ - putc(c, stderr); - } + if (imageInfoP->Comments[a+1] != '\0') + fprintf(fileP, "\nComment : "); + else + fprintf(fileP, "\n"); + } else + putc(c, fileP); } - fprintf(stderr, "\n"); + fprintf(fileP, "\n"); } - fprintf(stderr, "\n"); + fprintf(fileP, "\n"); } - - diff --git a/converter/other/exif.h b/converter/other/exif.h index 490e08ed..57eb745b 100644 --- a/converter/other/exif.h +++ b/converter/other/exif.h @@ -1,6 +1,9 @@ #ifndef EXIF_H_INCLUDED #define EXIF_H_INCLUDED +#include <stdio.h> +#include "netpbm/pm_c_util.h" + #define MAX_COMMENT 2000 #if MSVCRT @@ -35,23 +38,24 @@ typedef struct { int CompressionLevel; char Comments[MAX_COMMENT]; - unsigned char * ThumbnailPointer; /* Pointer at the thumbnail */ + const unsigned char * ThumbnailPointer; /* Pointer at the thumbnail */ unsigned ThumbnailSize; /* Size of thumbnail. */ - char * DatePointer; -}ImageInfo_t; + const char * DatePointer; +} exif_ImageInfo; /* Prototypes for exif.c functions. */ void -process_EXIF(unsigned char * const ExifSection, - unsigned int const length, - ImageInfo_t * const ImageInfoP, - int const ShowTags, - const char ** const errorP); +exif_parse(const unsigned char * const exifSection, + unsigned int const length, + exif_ImageInfo * const imageInfoP, + bool const wantTagTrace, + const char ** const errorP); void -ShowImageInfo(ImageInfo_t * const ImageInfoP); +exif_showImageInfo(const exif_ImageInfo * const imageInfoP, + FILE * const fileP); #endif diff --git a/converter/other/fiasco/Makefile b/converter/other/fiasco/Makefile index 16221d77..392e843c 100644 --- a/converter/other/fiasco/Makefile +++ b/converter/other/fiasco/Makefile @@ -11,8 +11,9 @@ COMP_INCLUDES = \ -I$(SRCDIR)/$(SUBDIR)/codec -I$(SRCDIR)/$(SUBDIR)/input \ -I$(SRCDIR)/$(SUBDIR)/output -I$(SRCDIR)/$(SUBDIR)/lib \ -BINARIES = pnmtofiasco fiascotopnm +PORTBINARIES = pnmtofiasco fiascotopnm +BINARIES = $(PORTBINARIES) MERGEBINARIES = $(BINARIES) SCRIPTS = @@ -24,21 +25,18 @@ FIASCOLIBS = codec/libfiasco_codec.a \ output/libfiasco_output.a \ lib/libfiasco_lib.a -COMMON_OBJECTS = binerror.o getopt.o getopt1.o params.o +ADDL_OBJECTS = binerror.o getopt.o getopt1.o params.o -OBJECTS = $(BINARIES:%=%.o) $(COMMON_OBJECTS) +OBJECTS = $(BINARIES:%=%.o) $(ADDL_OBJECTS) -MERGE_OBJECTS = $(BINARIES:%=%.o2) $(COMMON_OBJECTS) $(FIASCOLIBS) +MERGE_OBJECTS = $(BINARIES:%=%.o2) $(ADDL_OBJECTS) $(FIASCOLIBS) SUBDIRS = codec input output lib include $(SRCDIR)/common.mk -$(BINARIES):%:%.o $(COMMON_OBJECTS) $(FIASCOLIBS) $(NETPBMLIB) \ - $(LIBOPT) - $(LD) -o $@ $< $(COMMON_OBJECTS) \ - $(shell $(LIBOPT) $(FIASCOLIBS) $(NETPBMLIB)) $(MATHLIB) \ - $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) +$(BINARIES):%:%.o $(ADDL_OBJECTS) $(FIASCOLIBS) +$(BINARIES): LDFLAGS_TARGET = $(shell $(LIBOPT) $(FIASCOLIBS)) codec/libfiasco_codec.a: $(BUILDDIR)/$(SUBDIR)/codec FORCE $(MAKE) -C codec -f $(SRCDIR)/$(SUBDIR)/codec/Makefile \ diff --git a/converter/other/fiasco/codec/ip.c b/converter/other/fiasco/codec/ip.c index caa97baf..ade0d916 100644 --- a/converter/other/fiasco/codec/ip.c +++ b/converter/other/fiasco/codec/ip.c @@ -282,7 +282,7 @@ standard_ip_image_state (unsigned address, unsigned level, unsigned domain, real_t ip = 0, *imageptr, *stateptr; if (level > c->options.images_level) - error ("Level %d not supported.", level); + error ("We cannot interpret a Level %d image.", level); imageptr = &c->pixels [address * size_of_level (level)]; @@ -311,7 +311,7 @@ standard_ip_state_state (unsigned domain1, unsigned domain2, unsigned level, real_t ip = 0, *state1ptr, *state2ptr; if (level > c->options.images_level) - error ("Level %d not supported.", level); + error ("We cannot interpret and image with Level %d.", level); state1ptr = c->images_of_state [domain1] + address_of_level (level); state2ptr = c->images_of_state [domain2] + address_of_level (level); diff --git a/converter/other/fiasco/codec/tiling.c b/converter/other/fiasco/codec/tiling.c index 89fe3111..21e4428a 100644 --- a/converter/other/fiasco/codec/tiling.c +++ b/converter/other/fiasco/codec/tiling.c @@ -224,7 +224,7 @@ perform_tiling (const image_t *image, tiling_t *tiling) } else { - warning ("Unsupported image tiling method.\n" + warning ("We do not know the tiling method.\n" "Skipping image tiling step."); tiling->exponent = 0; } diff --git a/converter/other/fiasco/codec/wfa.h b/converter/other/fiasco/codec/wfa.h index 0b96ba8c..9253affd 100644 --- a/converter/other/fiasco/codec/wfa.h +++ b/converter/other/fiasco/codec/wfa.h @@ -19,7 +19,7 @@ #define MAXEDGES 5 #define MAXSTATES 6000 -#define MAXLABELS 2 /* only bintree supported anymore */ +#define MAXLABELS 2 /* only bintree possible anymore */ #define MAXLEVEL 22 #define FIASCO_BINFILE_RELEASE 2 diff --git a/converter/other/fiasco/display.c b/converter/other/fiasco/display.c index 368fd3c9..cf160329 100644 --- a/converter/other/fiasco/display.c +++ b/converter/other/fiasco/display.c @@ -307,7 +307,8 @@ alloc_ximage (x11_info_t *xinfo, unsigned width, unsigned height) shmem_flag = 0; if (fiasco_get_verbosity ()) fprintf (stderr, - "Shared memory not supported\nReverting to normal Xlib.\n"); + "Shared memory does not work on this system\n" + "Reverting to normal Xlib.\n"); } if (shmem_flag) diff --git a/converter/other/fiasco/lib/image.c b/converter/other/fiasco/lib/image.c index 56275f2e..fa3b2db5 100644 --- a/converter/other/fiasco/lib/image.c +++ b/converter/other/fiasco/lib/image.c @@ -449,7 +449,7 @@ write_image (const char *image_name, const image_t *image) if (image->format == FORMAT_4_2_0) { - warning ("Writing of images in 4:2:0 format not supported."); + warning ("We cannot write images in 4:2:0 format."); return; } diff --git a/converter/other/fiasco/params.c b/converter/other/fiasco/params.c index a4d843a8..afacbada 100644 --- a/converter/other/fiasco/params.c +++ b/converter/other/fiasco/params.c @@ -656,7 +656,7 @@ usage (const param_t *params, const char *progname, const char *synopsis, fprintf (stderr, "Usage: %s [OPTION]...%s\n", progname, non_opt_string ? non_opt_string : " "); if (synopsis != NULL) - fprintf (stderr, synopsis); + fprintf (stderr, "%s", synopsis); fprintf (stderr, "\n\n"); fprintf (stderr, "Mandatory or optional arguments to long options " "are mandatory or optional\nfor short options too. " diff --git a/converter/other/fiasco/pnmtofiasco.c b/converter/other/fiasco/pnmtofiasco.c index d78ff6b1..eebd09a9 100644 --- a/converter/other/fiasco/pnmtofiasco.c +++ b/converter/other/fiasco/pnmtofiasco.c @@ -170,7 +170,7 @@ main (int argc, char **argv) return 0; else { - fprintf (stderr, fiasco_get_error_message ()); + fprintf (stderr, "%s", fiasco_get_error_message ()); fprintf (stderr, "\n"); return 1; } diff --git a/converter/other/jbig/ANNOUNCE b/converter/other/jbig/ANNOUNCE deleted file mode 100644 index edbcc3f8..00000000 --- a/converter/other/jbig/ANNOUNCE +++ /dev/null @@ -1,243 +0,0 @@ - -Version 1.2 of the JBIG-KIT lossless image compression library available ------------------------------------------------------------------------- - -Markus Kuhn -- 2000-04-08 - - -The latest release of JBIG-KIT can be downloaded over the Internet -with anonymous ftp from - - ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/JBIG/jbigkit-1.2.tar.gz - http://www.cl.cam.ac.uk/~mgk25/download/jbigkit-1.2.tar.gz - -and from a number of other servers. - -JBIG-KIT implements a highly effective data compression algorithm for -bi-level high-resolution images such as fax pages or scanned -documents. - -JBIG-KIT provides a portable library of compression and decompression -functions with a documented interface that you can very easily include -into your image or document processing software. In addition, JBIG-KIT -provides ready-to-use compression and decompression programs with a -simple command line interface (similar to the converters found in Jef -Poskanzer's PBM graphics file conversion package). - -JBIG-KIT implements the specification - - International Standard ISO/IEC 11544:1993 and ITU-T Recommendation - T.82(1993), "Information technology - Coded representation of picture - and audio information - progressive bi-level image compression", - <http://www.itu.ch/itudoc/itu-t/rec/t/t82_23822.html>, - -which is commonly referred to as the "JBIG standard". JBIG (Joint -Bi-level Image experts Group) is the committee which developed this -international standard for the lossless compression of images using -arithmetic coding. Like the well-known compression algorithms JPEG and -MPEG, also JBIG has been developed and published by the International -Organization for Standardization (ISO) and the International -Telecommunication Union (ITU). See also - - http://www.jpeg.org/public/jbighomepage.htm - http://www.iso.ch/ - http://www.itu.ch/ - -The JBIG compression algorithm offers the following features: - - - Close to state-of-the-art lossless compression ratio for high - resolution bi-level images. - - - Around 1.1 to 1.5 times better compression ratio on typical - scanned documents compared to G4 fax compression (ITU-T T.6), - which has been the best compression algorithm for scanned - documents available prior to JBIG. - - - Up to 30 times better compression of scanned images with dithered - images compared to G4 fax compression. - - - Around 2 times better compression on typical 300 dpi documents - compared to 'gzip -9' on raw bitmaps. - - - Around 3-4 times better compression than GIF on typical 300 dpi - documents. - - - Even much better competitive compression results on computer - generated images which are free of scanning distortions. - - - JBIG supports hierarchical "progressive" encoding, that means it is - possible to encode a low resolution image first, followed by - resolution enhancement data. This allows for instance a document - browser to display already a good 75 dpi low resolution version of - an image, while the data necessary to reconstruct the full 300 dpi - version for laser printer reproduction is still arriving (say - over a slow network link or mass storage medium). - - - The various resolution layers of a JBIG image in progressive - encoding mode together require not much more space than a - normal non-progressive mode encoded image (which JBIG also - supports). - - - The progressive encoding mode utilizes a very sophisticated - resolution reduction algorithm which offers highest quality - low resolution versions that preserve the shape of characters as - well as the integrity of thin lines and dithered images. - - - JBIG supports multiple bit planes and can this way also be used - for greyscale and color images, although the main field of - application is compression of bi-level images, i.e. images with - only two different pixel values. For greyscale images with up to - 6 bit per pixel, JBIG performs superior to JPEG's lossless - mode. - -JBIG-KIT is free software under the GNU General Public License. For -other license arrangements contact the author. JBIG-KIT provides a -portable library implemented in ANSI/ISO C for encoding and decoding -JBIG data streams together with documentation. The library is not -intended for 8-bit or 16-bit machine architectures (e.g., old MS-DOS C -compilers) on which a number of very efficient optimization techniques -used in this software are not possible. For maximum performance, a -32-bit processor is required (64-bit systems work too, of course). On -architectures with 16-bit pointer arithmetic, only very small images -can be processed. - -Special features of the JBIG-KIT implementation are: - - - Fully reentrant multithread-capable design (no global or static - variables, isolated malloc()/free() calls, etc.). - - - Capable of handling incomplete and growing JBIG data streams in - order to allow earliest display of low resolution versions. - - - Capable of handling several incoming data streams simultaneously - in one single process and task. - - - Especially designed with applications in mind that want to display - incoming data as early as possible (e.g., similar to the way in - which Netscape Navigator handles incoming GIF images). - - - Implements all JBIG features and options including progressive and - sequential encoding, multiple bit planes, user specified - resolution reduction and deterministic prediction tables, adaptive - template changes for optimal performance on half-tone images, - deterministic prediction, typical prediction in lowest and - differential layers, various stripe orderings, etc. Only the SEQ - and HITOLO options are currently not supported by the decoder - (they are normally never required, but could be added later in - case of user requirements). - - - Efficient code, optimized utilization of 32-bit processor - registers. - - - Very easy to use documented C library interface. - - - Included Gray code conversion routines for efficient encoding - of greyscale images. - - - Ready-to-use pbmtojbg and jbgtopbm converters. - - -Changes in version 1.2 (2000-04-08): - - - bug in the decoder fixed, which caused the rest of the input file - to be skipped whenever a comment marker was encountered (special - thanks to Ben Rudiak-Gould <benrg@math.berkeley.edu> for - reporting this one) - -Changes in version 1.1 (1999-11-16): - - - serious bug in the encoder fixed, which for a very small - percentage of images has caused an unterminated linked list to be - created internally that could have been responsible for - segmentation violations or non-terminating encoders - (special thanks to Hisashi Saiga <saiga@itl.tnr.sharp.co.jp> for - tracking that one down) - - - minor bug in the "jbgtopbm -d" diagnostic output fixed - -Changes in version 1.0 (1998-04-11): - - - two bugs fixed that caused the encoder and decoder to fail - under certain modes of operation with several bit planes - - - added new functions jbg_split_planes(), jbg_dec_merge_planes(), - and jbg_dec_getsize_merged() for easy handling of greyscale - images - - - added support for compressing greyscale PGM files to pbmtojbg - and jbgtopbm - - - more changes to avoid paranoid compiler warnings - -Changes in version 0.9 (1996-01-09): - - - encoder won't break any more on input bitmap data with incorrect - zero padding - - - pbmtojbg displays a warning if input file has incorrect zero - padding - - - various minor improvements suggested by Stefan Willer - <Stefan.Willer@unnet.wupper.DE> - - - many minor changes in order to avoid warnings from paranoid - compilers - -Changes in version 0.8 (1995-09-20): - - - namespace cleared up, all names externally visible from the library - start now with jbg_ or JBG_ - - - minor non-critical bug fixed which caused library to fail compatibility - test and showed up especially on DEC Alpha systems - - - jbg_dec_gethight() is now called jbg_dec_getheight() - - - filenames conform now to MS-DOS limits - - - Bug in pbmtojbg fixed (handling of ASCII PBM files) - -Changes in version 0.7 (1995-06-10): - - - more problems on 16-bit int systems and on Macintosh systems fixed - (special thanks to Jean-Pierre Gachen <jpg11@calvanet.calvacom.fr>) - - - global Makefile - -Changes in version 0.6 (1995-06-08): - - - memory leak fixed - - - should now also work on systems where int is only 16-bit large - - - changes of the JBIG "Technical Corrigendum 1" included (special - thanks to Dr. Sebestyen from Siemens AG for sending me a copy - of the draft) - -First release: version 0.5 (1995-05-28) - - -Please send all questions, problem reports, patches, suggestions, -success stories, comments, etc. to - - mkuhn at acm.org - -I will try to provide free support and maintenance for this software -at least for the next few months depending on my available time. - -Y2K statement: JBIG-KIT does not handle any date and time related -data, therefore if JBIG-KIT causes you any problems related to date -and time overflows, this would indeed be most surprising. - -This library has been published in the hope that it will encourage the -development of good freely available scanned document handling and -transmission systems for the Internet so that large amounts of scanned -text can be made available to the global village easily. - -Happy compressing ... - -Markus Kuhn - --- -Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK -email: mkuhn at acm.org, home page: <http://www.cl.cam.ac.uk/~mgk25/> diff --git a/converter/other/jbig/Makefile b/converter/other/jbig/Makefile index 812bbbde..0625edd3 100644 --- a/converter/other/jbig/Makefile +++ b/converter/other/jbig/Makefile @@ -5,9 +5,14 @@ endif SUBDIR = converter/other/jbig VPATH=.:$(SRCDIR)/$(SUBDIR) +SUBDIRS = libjbig + include $(BUILDDIR)/config.mk -LIBJBIG_OBJECTS = jbig.o jbig_tab.o +# INTERNAL_JBIGLIB must be relative to the current directory, because it +# may end up in MERGE_OBJECTS, which must be relative. +INTERNAL_JBIGLIB = libjbig/libjbig.a +INTERNAL_JBIGHDR_DIR = $(SRCDIR)/$(SUBDIR)/libjbig/include EXTERN_INCLUDES = ifneq ($(JBIGHDR_DIR),NONE) @@ -18,32 +23,33 @@ endif ifneq ($(JBIGHDR_DIR),NONE) ifneq ($(JBIGLIB),NONE) - BINARIES = jbigtopnm pnmtojbig + PORTBINARIES = jbigtopnm pnmtojbig endif endif +BINARIES = $(PORTBINARIES) + SCRIPTS = -ifeq ($(JBIGLIB),$(BUILDDIR)/$(SUBDIR)/libjbig.a) +ifeq ($(JBIGLIB),$(INTERNAL_JBIGLIB)) JBIGLIB_DEP = $(JBIGLIB) else # It's not our internal version; user's on his own to make sure it's built endif -OBJECTS = $(BINARIES:%=%.o) $(LIBJBIG_OBJECTS) -MERGE_OBJECTS = $(BINARIES:%=%.o2) $(LIBJBIG_OBJECTS) +OBJECTS = $(BINARIES:%=%.o) +MERGE_OBJECTS = $(BINARIES:%=%.o2) all: $(BINARIES) include $(SRCDIR)/common.mk -$(BINARIES): %: %.o $(JBIGLIB_DEP) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $< \ - $(shell $(LIBOPT) $(NETPBMLIB) $(JBIGLIB)) $(MATHLIB) \ - $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - +$(BINARIES): %: %.o $(JBIGLIB_DEP) $(LIBOPT) +$(BINARIES): LDFLAGS_TARGET = $(shell $(LIBOPT) $(JBIGLIB)) -$(BUILDDIR)/$(SUBDIR)/libjbig.a: $(LIBJBIG_OBJECTS) - $(AR) -rc $@ $^ - $(RANLIB) $@ +$(INTERNAL_JBIGLIB): $(BUILDDIR)/$(SUBDIR)/libjbig FORCE + $(MAKE) -f $(SRCDIR)/$(SUBDIR)/libjbig/Makefile \ + -C $(dir $@) $(notdir $@) +.PHONY: FORCE +FORCE: diff --git a/converter/other/jbig/README 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_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", + <http://www.itu.int/rec/T-REC-T.82>, + +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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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. + + <signature of Ty Coon>, 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/jbig.h b/converter/other/jbig/libjbig/include/jbig.h index dd9a76f3..67994107 100644 --- a/converter/other/jbig/jbig.h +++ b/converter/other/jbig/libjbig/include/jbig.h @@ -1,21 +1,32 @@ /* - * Header file for the portable free JBIG compression library + * Header file for the portable JBIG compression library * - * Markus Kuhn -- mkuhn@acm.org - * - * $Id: jbig.h,v 1.9 1999-11-16 15:58:45+00 mgk25 Rel $ + * Copyright 1995-2014 -- Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ */ #ifndef JBG_H #define JBG_H #include <stddef.h> +#include "jbig_ar.h" /* * JBIG-KIT version number */ -#define JBG_VERSION "1.1" +#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 @@ -34,7 +45,7 @@ struct jbg_buf { }; /* - * Maximum number of allowed ATMOVEs per stripe + * Maximum number of ATMOVEs per stripe that decoder can handle */ #define JBG_ATMOVES_MAX 64 @@ -56,82 +67,30 @@ struct jbg_buf { #define JBG_DPPRIV 0x02 #define JBG_DPLAST 0x01 -#define JBG_DELAY_AT 0x100 /* delay ATMOVE until the first line of the next +/* 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.*/ + * 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 -#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 +#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 */ @@ -139,6 +98,8 @@ int arith_decode(struct jbg_ardec_state *s, int cx); 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 */ @@ -161,6 +122,10 @@ struct jbg_enc_state { /* 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 */ }; @@ -236,7 +201,7 @@ int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth, 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); + 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); @@ -245,17 +210,17 @@ 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 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); -long jbg_dec_getsize(const struct jbg_dec_state *s); +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); -long jbg_dec_getsize_merged(const struct jbg_dec_state *s); +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, int language); +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); @@ -263,5 +228,6 @@ 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/jbig.c b/converter/other/jbig/libjbig/jbig.c index 90295d8b..1ff867e8 100644 --- a/converter/other/jbig/jbig.c +++ b/converter/other/jbig/libjbig/jbig.c @@ -1,15 +1,13 @@ /* - * Portable Free JBIG image compression library + * Portable JBIG image compression library * - * Markus Kuhn -- mkuhn@acm.org - * - * $Id: jbig.c,v 1.12 2000-04-08 11:42:18+01 mgk25 Rel $ + * Copyright 1995-2014 -- Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ * * 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. + * 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 @@ -27,42 +25,22 @@ * * If you want to use this program under different license conditions, * then contact the author for an arrangement. - * - * It is possible that certain products which can be built using this - * software module might form inventions protected by patent rights in - * some countries (e.g., by patents about arithmetic coding algorithms - * owned by IBM and AT&T in the USA). Provision of this software by the - * author does NOT include any licences for any patents. In those - * countries where a patent licence is required for certain applications - * of this software module, you will have to obtain such a licence - * yourself. */ #ifdef DEBUG #include <stdio.h> +#else +#define NDEBUG #endif #include <stdlib.h> +#include <string.h> #include <assert.h> #include "jbig.h" - -/* optional export of arithmetic coder functions for test purposes */ -#ifdef TEST_CODEC -#define ARITH -#define ARITH_INL -#else -#define ARITH static -#ifdef __GNUC__ -#define ARITH_INL static __inline__ -#else -#define ARITH_INL static -#endif -#endif - -#define MX_MAX 23 /* maximal supported mx offset for - * adaptive template in the encoder */ +#define MX_MAX 127 + /* maximal mx offset for adaptive template in the encoder */ #define TPB2CX 0x195 /* contexts for TP special pixels */ #define TPB3CX 0x0e5 @@ -91,15 +69,15 @@ /* 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 $ "; + "JBIG-KIT " JBG_VERSION " -- (c) 1995-2014 Markus Kuhn -- " + "Licence: " JBG_LICENCE "\n"; /* - * the following array specifies for each combination of the 3 + * 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] = { +static const int iindex[8][3] = { { 2, 1, 0 }, /* no ordering bit set */ { -1, -1, -1}, /* SMID -> illegal combination */ { 2, 0, 1 }, /* ILEAVE */ @@ -110,96 +88,90 @@ static const int index[8][3] = { { -1, -1, -1 } /* SEQ + SMID + ILEAVE -> illegal combination */ }; +#define _(String) String /* to mark translatable string for GNU gettext */ /* - * Array [language][message] with text string error messages that correspond + * Array with English ASCII 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 */ - } +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 + * 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. */ -static void *checked_malloc(size_t size) +#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; - - 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. */ + * 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(%ld)\n", p, (long) size); + 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 size) +static void *checked_realloc(void *ptr, size_t nmemb, 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. */ + * 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, %ld)\n", p, ptr, (long) size); + fprintf(stderr, "%p = realloc(%p, %lu * %lu)\n", p, ptr, + (unsigned long) nmemb, (unsigned long) size); #endif return p; @@ -218,291 +190,6 @@ static void checked_free(void *ptr) -/* - * 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 @@ -532,7 +219,7 @@ static struct jbg_buf *jbg_buf_init(struct jbg_buf **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 = (struct jbg_buf *) checked_malloc(1, sizeof(struct jbg_buf)); } new_block->len = 0; new_block->next = NULL; @@ -668,7 +355,8 @@ static void jbg_buf_output(struct jbg_buf **head, /* - * Calculate y = ceil(x/2) applied n times. This function is used to + * 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. @@ -677,12 +365,405 @@ 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, @@ -693,12 +774,13 @@ void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, { unsigned long l, lx; int i; - size_t bufsize; - - extern char jbg_resred[], jbg_dptable[]; + 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; @@ -706,33 +788,32 @@ void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, 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; + 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 = checked_malloc(planes * sizeof(int)); + s->highres = (int *) 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); + 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] = checked_malloc(sizeof(unsigned char) * bufsize); + 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)); + 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->tp = (char *) checked_malloc(lx, sizeof(char)); + for (l = 0; l < lx; s->tp[l++] = 2) ; s->sde = NULL; return; @@ -759,12 +840,7 @@ int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, 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; - + jbg_set_default_l0(s); return s->d; } @@ -776,17 +852,12 @@ int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, */ void jbg_enc_layers(struct jbg_enc_state *s, int d) { - if (d < 0 || d > 255) + if (d < 0 || d > 31) 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; - + jbg_set_default_l0(s); return; } @@ -813,11 +884,11 @@ int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh) * 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) + 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 (l0 > 0) s->l0 = l0; if (mx >= 0 && my < 128) s->mx = mx; if (my >= 0 && my < 256) s->my = my; @@ -838,13 +909,17 @@ static void encode_sde(struct jbg_enc_state *s, 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; + 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 @@ -876,16 +951,19 @@ static void encode_sde(struct jbg_enc_state *s, 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; + 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, stripe != 0); + 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]; @@ -894,7 +972,7 @@ static void encode_sde(struct jbg_enc_state *s, c_all = 0; for (t = 0; t <= s->mx; t++) c[t] = 0; - if (stripe == 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 */ @@ -903,16 +981,16 @@ static void encode_sde(struct jbg_enc_state *s, /* initialize typical prediction */ ltp = 0; - if (stripe == 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); + while (p1 < hp && (ltp_old = (*p1++ == *q1++)) != 0) ; } else - while (p1 < hp && (ltp_old = (*p1++ == 0)) != 0); + while (p1 < hp && (ltp_old = (*p1++ == 0)) != 0) ; } if (layer == 0) { @@ -938,7 +1016,7 @@ static void encode_sde(struct jbg_enc_state *s, 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 ? */ + /* ^ 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) && @@ -949,19 +1027,24 @@ static void encode_sde(struct jbg_enc_state *s, 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 (y > 0) { + if (i > 0 || !reset) { q1 = hp - hbpl; - while (q1 < hp && (ltp = (*p1++ == *q1++)) != 0); + while (q1 < hp && (ltp = (*p1++ == *q1++)) != 0) ; } else - while (p1 < hp + hbpl && (ltp = (*p1++ == 0)) != 0); + while (p1 < hp + hbpl && (ltp = (*p1++ == 0)) != 0) ; arith_encode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX, ltp == ltp_old); #ifdef DEBUG @@ -985,26 +1068,35 @@ static void encode_sde(struct jbg_enc_state *s, */ 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; + 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 && y > 0) { + if (j < hbpl * 8 - 8 && (i > 0 || !reset)) { line_h2 |= *(hp - hbpl + 1); - if (y > 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]) - arith_encode(se, (((line_h2 >> 10) & 0x3e0) | - ((line_h1 >> (4 + s->tx[plane])) & 0x010) | + 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)), @@ -1014,9 +1106,20 @@ static void encode_sde(struct jbg_enc_state *s, #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); + 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); @@ -1024,13 +1127,21 @@ static void encode_sde(struct jbg_enc_state *s, /* three line template */ do { line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; - if (s->tx[plane]) + 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) | - ((line_h1 >> (6 + s->tx[plane])) & 0x004) | + ((line_h2 >> 12) & 0x078) | a | ((line_h1 >> 9) & 0x003)), (line_h1 >> 8) & 1); - else + } else arith_encode(se, (((line_h3 >> 8) & 0x380) | ((line_h2 >> 12) & 0x07c) | ((line_h1 >> 9) & 0x003)), @@ -1040,9 +1151,20 @@ static void encode_sde(struct jbg_enc_state *s, #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); + 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); @@ -1073,7 +1195,7 @@ static void encode_sde(struct jbg_enc_state *s, 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 ? */ + /* ^ 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) && @@ -1101,7 +1223,7 @@ static void encode_sde(struct jbg_enc_state *s, p0 = p1 = hp; if (i < hl - 1 && y < hy - 1) p0 = hp + hbpl; - if (y > 1) + if (i > 1 || !reset) line_l3 = (long)*(q2 - lbpl) << 8; else line_l3 = 0; @@ -1110,7 +1232,7 @@ static void encode_sde(struct jbg_enc_state *s, ltp = 1; for (j = 0; j < lx && ltp; q1++, q2++) { if (j < lbpl * 8 - 8) { - if (y > 1) + if (i > 1 || !reset) line_l3 |= *(q2 - lbpl + 1); line_l2 |= *(q2 + 1); line_l1 |= *(q1 + 1); @@ -1180,8 +1302,8 @@ static void encode_sde(struct jbg_enc_state *s, 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) { + 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; } @@ -1191,12 +1313,12 @@ static void encode_sde(struct jbg_enc_state *s, /* encode line */ for (j = 0; j < hx; lp1++, lp2++) { if ((j >> 1) < lbpl * 8 - 8) { - if (y > 1) + if (i > 1 || !reset) line_l3 |= *(lp2 - lbpl + 1); line_l2 |= *(lp2 + 1); line_l1 |= *(lp1 + 1); } - do { + do { /* ... while (j & 15 && j < hx) */ assert(hp - (s->lhp[s->highres[plane]][plane] + (stripe * hl + i) * hbpl) @@ -1206,15 +1328,15 @@ static void encode_sde(struct jbg_enc_state *s, (stripe * ll + (i>>1)) * lbpl) == (ptrdiff_t) j >> 4); - line_h1 |= *(hp++); + line_h1 |= *hp; if (j < hbpl * 8 - 8) { - if (y > 0) { - line_h2 |= *(hp - hbpl); - if (y > 1) - line_h3 |= *(hp - hbpl - hbpl); + if (i > 0 || !reset) { + line_h2 |= *(hp - hbpl + 1); + if (i > 1 || !reset) + line_h3 |= *(hp - hbpl - hbpl + 1); } } - do { + 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 */ @@ -1227,7 +1349,7 @@ static void encode_sde(struct jbg_enc_state *s, j += 2; #endif } else - do { + do { /* ... while (++j & 1 && j < hx) */ line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; /* deterministic prediction */ @@ -1286,12 +1408,20 @@ static void encode_sde(struct jbg_enc_state *s, } /* determine context */ - if (s->tx[plane]) - cx = (((line_h1 >> 9) & 0x003) | - ((line_h1 >> (4 + s->tx[plane])) & 0x010) | + 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 + } else cx = (((line_h1 >> 9) & 0x003) | ((line_h2 >> 13) & 0x01c) | ((line_h3 >> 11) & 0x020)); @@ -1318,6 +1448,7 @@ static void encode_sde(struct jbg_enc_state *s, } while (++j & 1 && j < hx); } while (j & 7 && j < hx); + hp++; } while (j & 15 && j < hx); } /* for (j = ...) */ @@ -1333,7 +1464,10 @@ static void encode_sde(struct jbg_enc_state *s, 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]); + 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) { @@ -1381,12 +1515,18 @@ static void encode_sde(struct jbg_enc_state *s, static void resolution_reduction(struct jbg_enc_state *s, int plane, int higher_layer) { - unsigned long hx, hy, lx, ly, hbpl, lbpl; + 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 i, j; + 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); @@ -1394,8 +1534,8 @@ static void resolution_reduction(struct jbg_enc_state *s, int plane, 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; + 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; @@ -1424,40 +1564,44 @@ static void resolution_reduction(struct jbg_enc_state *s, int plane, * 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; + + 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; + *(lp - 1) <<= lbpl * 8 - lx; + hp1 += hbpl; + hp2 += hbpl; + hp3 += hbpl; } - *(lp - 1) <<= lbpl * 8 - lx; - hp1 += hbpl; - hp2 += hbpl; - hp3 += hbpl; } #ifdef DEBUG @@ -1482,16 +1626,15 @@ static void resolution_reduction(struct jbg_enc_state *s, int plane, * 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 + * 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 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. + * 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) @@ -1587,12 +1730,12 @@ void jbg_int2dppriv(unsigned char *dptable, const char *internal) 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); + 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++) \ + for (j = 0; i >> j; j++) \ k |= ((i >> j) & 1) << trans[j]; \ dptable[(i + offset) >> 2] |= \ (internal[k + offset] & 3) << ((3 - (i&3)) << 1); \ @@ -1623,7 +1766,7 @@ void jbg_dppriv2int(char *internal, const unsigned char *dptable) #define FILL_TABLE2(offset, len, trans) \ for (i = 0; i < len; i++) { \ k = 0; \ - for (j = 0; j < 8; j++) \ + for (j = 0; i >> j; j++) \ k |= ((i >> j) & 1) << trans[j]; \ internal[k + offset] = \ (dptable[(i + offset) >> 2] >> ((3 - (i & 3)) << 1)) & 3; \ @@ -1644,20 +1787,19 @@ void jbg_dppriv2int(char *internal, const unsigned char *dptable) */ void jbg_enc_out(struct jbg_enc_state *s) { - long bpl; - unsigned char bih[20]; + 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]; - 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) + 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; @@ -1669,29 +1811,65 @@ void jbg_enc_out(struct jbg_enc_state *s) 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 = (s->xd + 7) / 8; /* bytes per line */ + 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 = ((s->yd >> s->d) + - ((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0; + 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 ***)); + 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 **)); + 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 *)); + checked_malloc(s->planes, sizeof(struct jbg_buf *)); for (plane = 0; plane < s->planes; plane++) s->sde[stripe][layer][plane] = SDE_TODO; } @@ -1699,29 +1877,7 @@ void jbg_enc_out(struct jbg_enc_state *s) } /* 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); + s->data_out(buf, 20, s->file); if ((s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) == (JBG_DPON | JBG_DPPRIV)) { /* write private table */ @@ -1751,27 +1907,68 @@ void jbg_enc_out(struct jbg_enc_state *s) * 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; + /* 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[index[order][STRIPE]]; + stripe = ii[iindex[order][STRIPE]]; if (s->order & JBG_HITOLO) - layer = s->dh - (ii[index[order][LAYER]] - s->dl); + layer = s->dh - (ii[iindex[order][LAYER]] - s->dl); else - layer = ii[index[order][LAYER]]; - plane = ii[index[order][PLANE]]; + 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; @@ -1784,7 +1981,7 @@ void jbg_enc_free(struct jbg_enc_state *s) int layer, plane; #ifdef DEBUG - fprintf(stderr, "jbg_enc_free(%p)\n", s); + fprintf(stderr, "jbg_enc_free(%p)\n", (void *) s); #endif /* clear buffers for SDEs */ @@ -1820,23 +2017,24 @@ void jbg_enc_free(struct jbg_enc_state *s) 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 a string - * written in the selected language and character set. + * Convert the error codes used by jbg_dec_in() into an English ASCII string */ -const char *jbg_strerror(int errnum, int language) +const char *jbg_strerror(int errnum) { - if (errnum < 0 || errnum >= NEMSG) + errnum >>= 4; + if (errnum < 0 || (unsigned) errnum >= sizeof(errmsg)/sizeof(errmsg[0])) 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]; + return errmsg[errnum]; } @@ -1880,8 +2078,8 @@ void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax, * 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. + * 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) @@ -1894,13 +2092,15 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, 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, shift, tx; + int pix, cx = 0, slntp, 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]]; + 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; @@ -1920,8 +2120,8 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, 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; + 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); @@ -1938,19 +2138,18 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, 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); + (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) { /* @@ -1960,7 +2159,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, for (; s->i < hl && y < hy; s->i++, y++) { /* adaptive template changes */ - if (x == 0) + 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]; @@ -1971,19 +2170,16 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, #endif } tx = s->tx[plane][layer - s->dl]; - shift = tx - ((s->options & JBG_LRLTWO) ? 5 : 3); + 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 (se->result == JBG_MORE || se->result == JBG_MARKER) + 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 'not typical' and has to be coded completely */ - s->pseudo = 0; - } else { + 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])) @@ -1995,7 +2191,9 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, 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 @@ -2071,14 +2269,24 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, if (s->options & JBG_LRLTWO) { /* two line template */ do { - if (tx) - pix = arith_decode(se, (((line_h2 >> 9) & 0x3e0) | - ((line_h1 >> shift) & 0x010) | + 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 + } else pix = arith_decode(se, (((line_h2 >> 9) & 0x3f0) | (line_h1 & 0x00f))); - if (se->result == JBG_MORE || se->result == JBG_MARKER) + if (pix < 0) goto leave; line_h1 = (line_h1 << 1) | pix; line_h2 <<= 1; @@ -2086,16 +2294,26 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, } else { /* three line template */ do { - if (tx) + 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) | - ((line_h1 >> shift) & 0x004) | + ((line_h2 >> 11) & 0x078) | a | (line_h1 & 0x003))); - else + } 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) + if (pix < 0) goto leave; line_h1 = (line_h1 << 1) | pix; @@ -2130,20 +2348,17 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, #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) + if ((s->options & JBG_TPDON) && s->pseudo) { + if ((s->lntp[plane][layer - s->dl] = arith_decode(se, TPDCX)) < 0) goto leave; - s->pseudo = 0; } - + s->pseudo = 0; /* * Layout of the variables line_h1, line_h2, line_h3, which contain @@ -2254,7 +2469,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, if (pix & 2) { if (tx) cx = ((line_h1 & 0x003) | - (((line_h1 << 2) >> shift) & 0x010) | + (((line_h1 << 2) >> (tx - 3)) & 0x010) | ((line_h2 >> 12) & 0x00c) | ((line_h3 >> 10) & 0x020)); else @@ -2270,7 +2485,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, cx |= (y & 1) << 11; pix = arith_decode(se, cx); - if (se->result == JBG_MORE || se->result == JBG_MARKER) + if (pix < 0) goto leave; } @@ -2316,23 +2531,38 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, /* - * Provide a new BIE fragment to the decoder. + * 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. * - * 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). + * 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) @@ -2340,9 +2570,8 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, 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; + unsigned char *dppriv; if (!cnt) cnt = &dummy_cnt; *cnt = 0; @@ -2354,92 +2583,112 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t 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[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; + 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; + 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; + 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]); - if (!s->planes || !s->xd || !s->yd || !s->l0) - return JBG_EINVAL; + /* 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; + return JBG_EINVAL | 9; s->my = s->buffer[17]; - if (s->mx > 32 || s->my > 0) - return JBG_EIMPL; +#if 0 + if (s->my > 0) + return JBG_EIMPL | 4; +#endif s->order = s->buffer[18]; - if (index[s->order & 7][0] < 0) - return JBG_EINVAL; + 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; + return JBG_EIMPL | 5; 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; - + s->stripes = jbg_stripes(s->l0, s->yd, s->d); + /* 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); + 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 = 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 *)); + 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] = 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); + 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] = 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); + 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++) @@ -2460,13 +2709,16 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, (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->buffer[s->bie_len++ - 20] = data[(*cnt)++]; + s->dppriv[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); + dppriv = (unsigned char *) s->dppriv; + s->dppriv = (char *) checked_malloc(6912, sizeof(char)); + jbg_dppriv2int(s->dppriv, dppriv); + checked_free(dppriv); } /* @@ -2516,7 +2768,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, /* now the buffer is filled with exactly one marker segment */ switch (s->buffer[1]) { case MARKER_COMMENT: - s->comment_skip = + s->comment_skip = (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) | ((long) s->buffer[4] << 8) | (long) s->buffer[5]); break; @@ -2531,21 +2783,21 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, 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; + return JBG_EINVAL | 11; + if (s->at_ty[s->at_moves] != 0) + return JBG_EIMPL | 6; s->at_moves++; } else - return JBG_EINVAL; + 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 || !(s->options & JBG_VLENGTH)) - return JBG_EINVAL; + 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 = - ((s->yd >> s->d) + - ((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0; + s->stripes = jbg_stripes(s->l0, s->yd, s->d); break; case MARKER_ABORT: return JBG_EABORT; @@ -2555,13 +2807,13 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, /* 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 + 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[index[s->order & 7][PLANE]]] - [s->ii[index[s->order & 7][LAYER]] - s->dl] = + 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 */ @@ -2572,12 +2824,12 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, /* 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; + 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 */ @@ -2593,12 +2845,16 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, /* 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 (index[s->order & 7][LAYER] == 0 && i < 0) { + 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) { @@ -2629,7 +2885,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, "%02x %02x %02x %02x ...\n", data[*cnt], data[*cnt+1], data[*cnt+2], data[*cnt+3]); #endif - return JBG_EINVAL; + return JBG_EINVAL | 14; } } @@ -2641,15 +2897,16 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, /* * 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. + * function in order to find out the width of the image. Returns 0 if + * there is no image available yet. */ -long jbg_dec_getwidth(const struct jbg_dec_state *s) +unsigned long jbg_dec_getwidth(const struct jbg_dec_state *s) { if (s->d < 0) - return -1; - if (index[s->order & 7][LAYER] == 0) { + return 0; + if (iindex[s->order & 7][LAYER] == 0) { if (s->ii[0] < 1) - return -1; + return 0; else return jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)); } @@ -2660,15 +2917,16 @@ long jbg_dec_getwidth(const struct jbg_dec_state *s) /* * 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. + * function in order to find out the height of the image. Returns 0 if + * there is no image available yet. */ -long jbg_dec_getheight(const struct jbg_dec_state *s) +unsigned long jbg_dec_getheight(const struct jbg_dec_state *s) { if (s->d < 0) - return -1; - if (index[s->order & 7][LAYER] == 0) { + return 0; + if (iindex[s->order & 7][LAYER] == 0) { if (s->ii[0] < 1) - return -1; + return 0; else return jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); } @@ -2679,13 +2937,14 @@ long jbg_dec_getheight(const struct jbg_dec_state *s) /* * 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. + * 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 (index[s->order & 7][LAYER] == 0) { + if (iindex[s->order & 7][LAYER] == 0) { if (s->ii[0] < 1) return NULL; else @@ -2701,20 +2960,20 @@ unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane) * 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) +unsigned long jbg_dec_getsize(const struct jbg_dec_state *s) { if (s->d < 0) - return -1; - if (index[s->order & 7][LAYER] == 0) { + return 0; + if (iindex[s->order & 7][LAYER] == 0) { if (s->ii[0] < 1) - return -1; + return 0; else return - ((jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) + 7) / 8) * + 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 ((s->xd + 7) / 8) * s->yd; + return jbg_ceil_half(s->xd, 3) * s->yd; } @@ -2723,16 +2982,16 @@ long jbg_dec_getsize(const struct jbg_dec_state *s) * 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) +unsigned long jbg_dec_getsize_merged(const struct jbg_dec_state *s) { if (s->d < 0) - return -1; - if (index[s->order & 7][LAYER] == 0) { + return 0; + if (iindex[s->order & 7][LAYER] == 0) { if (s->ii[0] < 1) - return -1; + return 0; else return - jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) * + 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); } @@ -2770,6 +3029,8 @@ void jbg_dec_free(struct jbg_dec_state *s) 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; @@ -2790,11 +3051,10 @@ void jbg_split_planes(unsigned long x, unsigned long y, int has_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; + unsigned long bpl = jbg_ceil_half(x, 3); /* bytes per line in dest plane */ + unsigned long line, i; + unsigned 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; @@ -2818,7 +3078,7 @@ void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, bits = (prev | *src) >> bitno; /* go to next *src byte, but keep old */ if (bitno == 0) - prev = *src++; + prev = *src++ << 8; /* make space for inserting new bit */ dest[p][bpl * line + i] <<= 1; /* insert bit, if requested apply Gray encoding */ @@ -2831,7 +3091,7 @@ void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, } /* skip unused *src bytes */ for (;p < has_planes; p++) - if (((has_planes - 1 - p) & 7) == 0) + if (((msb - p) & 7) == 0) src++; } } @@ -2845,16 +3105,16 @@ void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, /* * Merge the separate bit planes decoded by the JBIG decoder into an * integer pixel field. This is essentially the counterpart to - * jbg_split_planes(). */ + * 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 long bpl, line, i; + unsigned k = 8; + int p; unsigned char buf[BUFLEN]; unsigned char *bp = buf; unsigned char **src; @@ -2866,12 +3126,11 @@ void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, x = jbg_dec_getwidth(s); y = jbg_dec_getheight(s); - if (x <= 0 || y <= 0) + 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 */ + bpl = jbg_ceil_half(x, 3); /* bytes per line in src plane */ - if (index[s->order & 7][LAYER] == 0) + if (iindex[s->order & 7][LAYER] == 0) if (s->ii[0] < 1) return; else @@ -2882,12 +3141,13 @@ void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, 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 = 0; + for (p = 0; p < s->planes;) { /* dest bytes loop */ + do { v = (v << 1) | - (((src[p+q][bpl * line + i] >> (7 - k)) & 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); @@ -2903,3 +3163,123 @@ void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, 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/jbig.doc b/converter/other/jbig/libjbig/jbig.txt index 10eeda80..bdc14b17 100644 --- a/converter/other/jbig/jbig.doc +++ b/converter/other/jbig/libjbig/jbig.txt @@ -2,47 +2,56 @@ Using the JBIG-KIT library -------------------------- -Markus Kuhn -- 1998-04-10 +Markus Kuhn -- 2013-09-10 -This text explains how to include the functions provided by the -JBIG-KIT portable image compression library into your application -software. +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 +<http://www.itu.int/rec/T-REC-T.85/en>, 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 -Below follows a short introduction into some technical aspects of the -JBIG standard. More detailed information is provided in the -"Introduction and overview" section of the JBIG standard. Information -about how to obtain a copy of the standard is available on the -Internet from <http://www.itu.ch/> or <http://www.iso.ch/>. +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 <http://www.itu.int/rec/T-REC-T.82/en> or +<http://www.iso.ch/>. Image data encoded with the JBIG algorithm is separated into planes, layers, and stripes. Each plane contains one bit per pixel. The number of planes stored in a JBIG data stream is the number of bits per pixel. Resolution layers are numbered from 0 to D with 0 being the -layer with the lowest resolution and D the layer with the highest one. -Each next higher resolution layer has exactly twice the number of rows -and columns than the previous one. Layer 0 is encoded independently of -any other data, all other resolution layers are encoded as only the -difference between the next lower and the current layer. For -applications that require very quick access to parts of an image it is -possible to divide an image into several horizontal stripes. All -stripes of one resolution layer have equal size except perhaps the -final one. The number of stripes of an image is equal in all -resolution layers and in all bit planes. +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). 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: +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: +------------------------------------------------+ @@ -57,6 +66,10 @@ specific information. A BIE looks like this: | | +------------------------------------------------+ | | + | optional floating marker segments | + | | + +------------------------------------------------+ + | | | stripe data entity | | | +------------------------------------------------+ @@ -85,58 +98,58 @@ 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. +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 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: +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 on a typeless file system as JBIG encoded and to allow + 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 like a textual - description, information about the meaning of various bit planes, - the physical size and resolution of the document, etc. + - 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 that ensures image integrity + - a checksum to ensure image integrity - encryption and signature mechanisms - many things more -Raw BIE data streams alone are consequently no suitable format for +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 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. +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 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. +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 -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. +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: @@ -158,28 +171,29 @@ 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. +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 several bit planes, the JBIG-KIT +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 +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. +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 greyscale images, by using a Gray code instead of a simple binary +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 +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) 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: +(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 @@ -198,7 +212,7 @@ 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 +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 @@ -212,7 +226,7 @@ during the transmission. 2.2 A simple compression application -In order to use JBIG-KIT in your application, just link libjbig.a to +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 @@ -222,10 +236,10 @@ directory and put the line into your source code. -The library interface follows the concepts of object-oriented -programming. You have to declare a variable (object) +The library interface follows object-oriented programming principles. +You have to declare a variable (object) - struct jbg_enc_state se; + struct jbg_enc_state s; which contains the current status of an encoder. Then you initialize the encoder by calling the constructor function @@ -238,12 +252,12 @@ the encoder by calling the constructor function The parameters have the following meaning: - s A pointer to the jbg_enc_state structure which you want + s A pointer to the jbg_enc_state structure that you want to initialize. - x The width of your image. + x The width of your image in pixels. - y The height of your image. + y The height of your image in pixels (lines). pl the number of bitmap planes you want to encode. @@ -251,36 +265,37 @@ The parameters have the following meaning: 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. + 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(). After this, a call -to the destructor function +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 memory allocated by the previous functions. +will release any heap 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 minimal example application, which sends the BIE of the above bitmap +to stdout, looks like this: --------------------------------------------------------------------------- /* A sample JBIG encoding application */ @@ -332,7 +347,7 @@ following default values are used for various compression parameters: - 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 + 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). @@ -340,7 +355,7 @@ following default values are used for various compression parameters: TPDON and DPON). - The default resolution reduction table and the default deterministic - prediction tables are used + 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). @@ -354,14 +369,16 @@ 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 +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 resolution layers with 75, 150 and 300 dots per inch. +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 @@ -381,26 +398,26 @@ resolution directly, then call 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 +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 +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, one calls +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(), one calls +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 which will represent +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. +query the layer of the full image resolution. A number of other more exotic options of the JBIG algorithm can be modified by calling @@ -418,14 +435,14 @@ the SDEs are stored in the BIE. The bits have the following meaning: 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 + 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 + jbig.c decoder currently does not) so you should normally not use it. JBG_SEQ Usually, at first all stripes of one resolution layer @@ -434,10 +451,10 @@ the SDEs are stored in the BIE. The bits have the following meaning: 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. + 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 3 loops over all stripes, + 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. @@ -445,8 +462,8 @@ the SDEs are stored in the BIE. The bits have the following meaning: 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 +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: @@ -482,15 +499,15 @@ some of the optional algorithms defined by JBIG: 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 + 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 color have to be encoded at all. + 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 which does not support this + for cheap JBIG hardware that might not support this option. JBG_TPBON Like JBG_TPDON this activates the "typical prediction" @@ -501,12 +518,12 @@ some of the optional algorithms defined by JBIG: 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 + 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 only might perhaps want - to deactivate it if the default resolution reduction - algorithm is replaced by a new one. + 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 @@ -514,31 +531,32 @@ some of the optional algorithms defined by JBIG: 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 + 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. 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, +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. 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. +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 +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 +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, @@ -547,8 +565,8 @@ function 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 +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 @@ -557,7 +575,7 @@ 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 +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 @@ -568,7 +586,7 @@ the pixel integer values will be used instead of the Gray code. Plane 3 Decompressing an image -Like with the compression functions, if you want to use the JBIG-KIT +Like with the compression functions, if you want to use the jbig.c library, you have to put the line #include "jbig.h" @@ -603,19 +621,19 @@ 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. +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 - long jbg_dec_getwidth(struct jbg_dec_state *s); - long jbg_dec_getheight(struct jbg_dec_state *s); + 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); - long jbg_dec_getsize(struct jbg_dec_state *s); + 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 @@ -628,14 +646,14 @@ The function void (*data_out)(unsigned char *start, size_t len, void *file), void *file); -allows you to merge the bitplanes that can be accessed individually +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 - long jbg_dec_getsize_merged(const struct jbg_dec_state *s); + 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. @@ -683,34 +701,105 @@ and the memory can be released. The function - const char *jbg_strerror(int errnum, int language); + const char *jbg_strerror(int errnum); -returns a pointer to a short single line test message which explains +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 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 +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 horizontal offset mx of the adaptive template pixel - must not be larger than 32 and the maximal vertical offset must - be zero. + - 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, + für Betriebssysteme, IMMD IV, Universität Erlangen-Nürnberg, Erlangen, July 1995. (German, 62 pages) <http://www.cl.cam.ac.uk/~mgk25/kuhn-sta.pdf> 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 <assert.h> +#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 <string.h> +#include <jasper/jasper.h> + #include "pm_c_util.h" #include "pam.h" #include "shhopt.h" #include "nstring.h" #include "mallocvar.h" -#include <jasper/jasper.h> #include "libjasper_compat.h" enum compmode {COMPMODE_INTEGER, COMPMODE_REAL}; diff --git a/converter/other/jpeg2000/libjasper/base/jas_image.c b/converter/other/jpeg2000/libjasper/base/jas_image.c index 8d62b48d..903b45c6 100644 --- a/converter/other/jpeg2000/libjasper/base/jas_image.c +++ b/converter/other/jpeg2000/libjasper/base/jas_image.c @@ -623,7 +623,7 @@ int jas_image_getfmt(jas_stream_t *in) int found; int i; - /* Check for data in each of the supported formats. */ + /* Check for data in each of the formats we know. */ found = 0; for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) { diff --git a/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h b/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h index 558f4368..6e914efd 100644 --- a/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h +++ b/converter/other/jpeg2000/libjasper/include/jasper/jas_image.h @@ -171,9 +171,9 @@ extern "C" { #define JAS_IMAGE_CT_GRAY_Y 0 -/******************************************************************************\ +/*****************************************************************************\ * Image class and supporting classes. -\******************************************************************************/ +\*****************************************************************************/ /* Image component class. */ @@ -294,7 +294,7 @@ typedef struct { \******************************************************************************/ #define JAS_IMAGE_MAXFMTS 32 -/* The maximum number of image data formats supported. */ +/* The maximum number of image data formats we can handle. */ /* Image format-dependent operations. */ @@ -530,57 +530,57 @@ int jas_image_getfmt(jas_stream_t *in); * Image format-dependent operations. \******************************************************************************/ -#if !defined(EXCLUDE_JPG_SUPPORT) -/* Format-dependent operations for JPG support. */ +#if !defined(EXCLUDE_JPG_CAPABILITY) +/* Format-dependent operations for JPG capability. */ jas_image_t *jpg_decode(jas_stream_t *in, char *optstr); int jpg_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int jpg_validate(jas_stream_t *in); #endif -#if !defined(EXCLUDE_MIF_SUPPORT) -/* Format-dependent operations for MIF support. */ +#if !defined(EXCLUDE_MIF_CAPABILITY) +/* Format-dependent operations for MIF capability. */ jas_image_t *mif_decode(jas_stream_t *in, char *optstr); int mif_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int mif_validate(jas_stream_t *in); #endif -#if !defined(EXCLUDE_PNM_SUPPORT) -/* Format-dependent operations for PNM support. */ +#if !defined(EXCLUDE_PNM_CAPABILITY) +/* Format-dependent operations for PNM capability. */ jas_image_t *pnm_decode(jas_stream_t *in, char *optstr); int pnm_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int pnm_validate(jas_stream_t *in); #endif -#if !defined(EXCLUDE_RAS_SUPPORT) -/* Format-dependent operations for Sun Rasterfile support. */ +#if !defined(EXCLUDE_RAS_CAPABILITY) +/* Format-dependent operations for Sun Rasterfile capability. */ jas_image_t *ras_decode(jas_stream_t *in, char *optstr); int ras_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int ras_validate(jas_stream_t *in); #endif -#if !defined(EXCLUDE_BMP_SUPPORT) -/* Format-dependent operations for BMP support. */ +#if !defined(EXCLUDE_BMP_CAPABILITY) +/* Format-dependent operations for BMP capability. */ jas_image_t *bmp_decode(jas_stream_t *in, char *optstr); int bmp_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int bmp_validate(jas_stream_t *in); #endif -#if !defined(EXCLUDE_JP2_SUPPORT) -/* Format-dependent operations for JP2 support. */ +#if !defined(EXCLUDE_JP2_CAPABILITY) +/* Format-dependent operations for JP2 capability. */ jas_image_t *jp2_decode(jas_stream_t *in, char *optstr); int jp2_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int jp2_validate(jas_stream_t *in); #endif -#if !defined(EXCLUDE_JPC_SUPPORT) -/* Format-dependent operations for JPEG-2000 code stream support. */ +#if !defined(EXCLUDE_JPC_CAPABILITY) +/* Format-dependent operations for JPEG-2000 code stream capability. */ jas_image_t *jpc_decode(jas_stream_t *in, char *optstr); int jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int jpc_validate(jas_stream_t *in); #endif -#if !defined(EXCLUDE_PGX_SUPPORT) -/* Format-dependent operations for PGX support. */ +#if !defined(EXCLUDE_PGX_CAPABILITY) +/* Format-dependent operations for PGX capability. */ jas_image_t *pgx_decode(jas_stream_t *in, char *optstr); int pgx_encode(jas_image_t *image, jas_stream_t *out, char *optstr); int pgx_validate(jas_stream_t *in); diff --git a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c index aaebf411..91ce6c51 100644 --- a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c +++ b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c @@ -297,9 +297,9 @@ jas_image_t *jp2_decode(jas_stream_t *in, char *optstr) jas_eprintf("warning: component data type mismatch\n"); } - /* Is the compression type supported? */ + /* Can we handle the compression type? */ if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) { - jas_eprintf("error: unsupported compression type\n"); + jas_eprintf("error: not capable of this compression type\n"); goto error; } diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c b/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c index ffe6aab5..559f36cf 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_cs.c @@ -1461,8 +1461,6 @@ static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out) { - /* If this function is called, we are trying to write an unsupported - type of marker segment. Return with an error indication. */ return -1; } diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c index b52dcc27..d17e9aa3 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c @@ -346,7 +346,7 @@ static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image) if (jas_image_cmptbrx(image, cmptno) + jas_image_cmpthstep(image, cmptno) <= jas_image_brx(image) || jas_image_cmptbry(image, cmptno) + jas_image_cmptvstep(image, cmptno) <= jas_image_bry(image)) { - fprintf(stderr, "unsupported image type\n"); + fprintf(stderr, "We don't know how to interpret this image type\n"); goto error; } /* Note: We ought to be calculating the LCMs here. Fix some day. */ diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c b/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c index 1d41d5c5..80bc5aa5 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c @@ -900,8 +900,8 @@ static void jpc_ns_analyze(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) startptr += interstep; } } else { - /* The reversible integer-to-integer mode is not supported - for this transform. */ + /* The reversible integer-to-integer mode is not valid for this + transform. */ abort(); } } @@ -973,8 +973,8 @@ static void jpc_ns_synthesize(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) startptr += interstep; } } else { - /* The reversible integer-to-integer mode is not supported - for this transform. */ + /* The reversible integer-to-integer mode is not valid + for this transform. */ abort(); } } diff --git a/converter/other/jpeg2000/pamtojpeg2k.c b/converter/other/jpeg2000/pamtojpeg2k.c index 15ea0f31..349018e1 100644 --- a/converter/other/jpeg2000/pamtojpeg2k.c +++ b/converter/other/jpeg2000/pamtojpeg2k.c @@ -13,13 +13,14 @@ #define _XOPEN_SOURCE 600 #include <string.h> +#include <jasper/jasper.h> + #include "pm_c_util.h" #include "pam.h" #include "shhopt.h" #include "nstring.h" #include "mallocvar.h" -#include <jasper/jasper.h> #include "libjasper_compat.h" diff --git a/converter/other/jpegtopnm.c b/converter/other/jpegtopnm.c index f09cd04f..ab3b18e5 100644 --- a/converter/other/jpegtopnm.c +++ b/converter/other/jpegtopnm.c @@ -652,19 +652,20 @@ print_exif_info(struct jpeg_marker_struct const marker) { Dump as informational messages the contents of the Jpeg miscellaneous marker 'marker', assuming it is an Exif header. -----------------------------------------------------------------------------*/ - ImageInfo_t imageInfo; + bool const wantTagTrace = false; + exif_ImageInfo imageInfo; const char * error; assert(marker.data_length >= 6); - process_EXIF(marker.data+6, marker.data_length-6, - &imageInfo, FALSE, &error); + exif_parse(marker.data+6, marker.data_length-6, + &imageInfo, wantTagTrace, &error); if (error) { pm_message("EXIF header is invalid. %s", error); pm_strfree(error); } else - ShowImageInfo(&imageInfo); + exif_showImageInfo(&imageInfo, stderr); } @@ -700,8 +701,7 @@ dump_exif(struct jpeg_decompress_struct const cinfo) { found_one = FALSE; /* initial value */ - for (markerP = cinfo.marker_list; - markerP; markerP = markerP->next) + for (markerP = cinfo.marker_list; markerP; markerP = markerP->next) if (is_exif(*markerP)) { pm_message("EXIF INFO:"); print_exif_info(*markerP); diff --git a/converter/other/pamtosvg/Makefile b/converter/other/pamtosvg/Makefile index 8b033020..83f150d0 100644 --- a/converter/other/pamtosvg/Makefile +++ b/converter/other/pamtosvg/Makefile @@ -7,26 +7,13 @@ VPATH=.:$(SRCDIR)/$(SUBDIR) include $(BUILDDIR)/config.mk -BINARIES = pamtosvg +PORTBINARIES = pamtosvg -PAMTOSVG_OBJECTS = \ - pamtosvg.o \ - output-svg.o \ - fit.o \ - spline.o \ - curve.o \ - vector.o \ - epsilon-equal.o \ - autotrace.o \ - pxl-outline.o \ - bitmap.o \ - thin-image.o \ - logreport.o \ - exception.o \ - image-proc.o \ +BINARIES = $(PORTBINARIES) + +MERGEBINARIES = $(BINARIES) -MERGE_OBJECTS = \ - pamtosvg.o2 \ +ADDL_OBJECTS = \ output-svg.o \ fit.o \ spline.o \ @@ -41,15 +28,12 @@ MERGE_OBJECTS = \ exception.o \ image-proc.o \ -OBJECTS = $(PAMTOSVG_OBJECTS) +OBJECTS = pamtosvg.o $(ADDL_OBJECTS) -MERGEBINARIES = $(BINARIES) +MERGE_OBJECTS = pamtosvg.o2 $(ADDL_OBJECTS) all: $(BINARIES) include $(SRCDIR)/common.mk -pamtosvg: $(PAMTOSVG_OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $(PAMTOSVG_OBJECTS) \ - $(shell $(LIBOPT) $(NETPBMLIB)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) +pamtosvg: $(ADDL_OBJECTS) diff --git a/converter/other/pamtosvg/bitmap.h b/converter/other/pamtosvg/bitmap.h index 7334f138..b979e0c0 100644 --- a/converter/other/pamtosvg/bitmap.h +++ b/converter/other/pamtosvg/bitmap.h @@ -36,7 +36,7 @@ at_bitmap_type * at_bitmap_new(unsigned short width, unsigned int planes); at_bitmap_type * at_bitmap_copy(at_bitmap_type * src); -/* We have to export functions that supports internal datum +/* We have to export functions that allows internal datum access. Such functions might be useful for at_bitmap_new user. */ unsigned short at_bitmap_get_width (at_bitmap_type * bitmap); diff --git a/converter/other/pamtosvg/image-proc.c b/converter/other/pamtosvg/image-proc.c index b044b547..d025ee1e 100644 --- a/converter/other/pamtosvg/image-proc.c +++ b/converter/other/pamtosvg/image-proc.c @@ -330,7 +330,7 @@ binarize(bitmap_type *bitmap) } else { - WARNING1("binarize: %u-plane images are not supported", spp); + WARNING1("binarize: don't know how to interpret %u-plane images", spp); } } diff --git a/converter/other/pamtosvg/thin-image.c b/converter/other/pamtosvg/thin-image.c index 86d1037c..364f67cc 100644 --- a/converter/other/pamtosvg/thin-image.c +++ b/converter/other/pamtosvg/thin-image.c @@ -189,7 +189,7 @@ thin_image(bitmap_type *image, bool bgSpec, pixel bg, default: { - LOG1 ("thin_image: %u-plane images are not supported", spp); + LOG1 ("thin_image: Don't know how to interpret %u-plane images", spp); at_exception_fatal(exp, "thin_image: wrong plane images are passed"); goto cleanup; } diff --git a/converter/other/pamtotiff.c b/converter/other/pamtotiff.c index 0206678d..f2cc0e2b 100644 --- a/converter/other/pamtotiff.c +++ b/converter/other/pamtotiff.c @@ -53,16 +53,19 @@ #define COMPRESSION_ADOBE_DEFLATE 8 #endif -struct sizeset { +typedef struct { bool b1, b2, b4, b8; -}; +} SizeSet; +typedef enum { TMPFILE, DIRECT_CREATE, DIRECT_APPEND } WriteMethod; -struct cmdlineInfo { +typedef enum { MUST_EXIST, MAY_CREATE } CreatePolicy; + +typedef struct { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *input_filespec; /* Filespecs of input files */ + const char * inputFileName; int compression; /* COMPRESSION Tiff tag value, that corresponds to the compression option the user specified, or -1 if he didn't specify any. @@ -79,13 +82,14 @@ struct cmdlineInfo { float xresolution; /* XRESOLUTION Tiff tag value or -1 for none */ float yresolution; /* YRESOLUTION Tiff tag value or -1 for none */ int resolutionunit; /* RESOLUTIONUNIT Tiff tag value */ - struct sizeset indexsizeAllowed; + SizeSet indexsizeAllowed; /* Which bit widths are allowable in a raster of palette indices */ unsigned int verbose; - unsigned int append; + WriteMethod writeMethod; /* Output mode */ + const char * output; /* -output option value. NULL if none. */ float resolution; /* X and Y resolution */ struct optNameValue * taglist; -}; +} CmdlineInfo; @@ -96,7 +100,7 @@ validateTagList(struct optNameValue const taglist[]) { for (i = 0; taglist[i].name; ++i) { const char * const tagName = taglist[i].name; const tagDefinition * tagDefP = tagDefFind(tagName); - + if (!tagDefP) pm_error("Unknown tag name '%s'", tagName); else { @@ -131,9 +135,9 @@ validateTagList(struct optNameValue const taglist[]) { static void -parseCommandLine(int argc, - char ** const argv, - struct cmdlineInfo * const cmdlineP) { +parseCommandLine(int argc, + const char ** const argv, + CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. @@ -147,8 +151,9 @@ parseCommandLine(int argc, char * indexbits; char * resolutionunit; - unsigned int predictorSpec, rowsperstripSpec, xresolutionSpec, - yresolutionSpec, indexbitsSpec, resolutionunitSpec, tagSpec; + unsigned int appendSpec, outputSpec, predictorSpec, rowsperstripSpec, + xresolutionSpec, yresolutionSpec, indexbitsSpec, + resolutionunitSpec, tagSpec; unsigned int option_def_index; @@ -156,7 +161,6 @@ parseCommandLine(int argc, option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); - OPTENT3(0, "append", OPT_FLAG, NULL, &cmdlineP->append, 0); OPTENT3(0, "none", OPT_FLAG, NULL, &none, 0); OPTENT3(0, "packbits", OPT_FLAG, NULL, &packbits, 0); OPTENT3(0, "lzw", OPT_FLAG, NULL, &lzw, 0); @@ -174,17 +178,20 @@ parseCommandLine(int argc, OPTENT3(0, "mw", OPT_FLAG, NULL, &cmdlineP->miniswhite, 0); OPTENT3(0, "truecolor", OPT_FLAG, NULL, &cmdlineP->truecolor, 0); OPTENT3(0, "color", OPT_FLAG, NULL, &cmdlineP->color, 0); - OPTENT3(0, "predictor", OPT_UINT, &cmdlineP->predictor, + OPTENT3(0, "append", OPT_FLAG, NULL, &appendSpec, 0); + OPTENT3(0, "output", OPT_STRING, &cmdlineP->output, + &outputSpec, 0); + OPTENT3(0, "predictor", OPT_UINT, &cmdlineP->predictor, &predictorSpec, 0); - OPTENT3(0, "rowsperstrip", OPT_UINT, &cmdlineP->rowsperstrip, + OPTENT3(0, "rowsperstrip", OPT_UINT, &cmdlineP->rowsperstrip, &rowsperstripSpec, 0); - OPTENT3(0, "xresolution", OPT_FLOAT, &cmdlineP->xresolution, + OPTENT3(0, "xresolution", OPT_FLOAT, &cmdlineP->xresolution, &xresolutionSpec, 0); - OPTENT3(0, "yresolution", OPT_FLOAT, &cmdlineP->yresolution, + OPTENT3(0, "yresolution", OPT_FLOAT, &cmdlineP->yresolution, &yresolutionSpec, 0); OPTENT3(0, "resolutionunit", OPT_STRING, &resolutionunit, &resolutionunitSpec, 0); - OPTENT3(0, "indexbits", OPT_STRING, &indexbits, + OPTENT3(0, "indexbits", OPT_STRING, &indexbits, &indexbitsSpec, 0); OPTENT3(0, "tag", OPT_NAMELIST, &cmdlineP->taglist, &tagSpec, 0); @@ -192,14 +199,14 @@ parseCommandLine(int argc, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char**)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (none + packbits + lzw + g3 + g4 + flate + adobeflate > 1) pm_error("You specified more than one compression option. " "Only one of -none, -packbits, -lze, -g3, and -g4 " "is allowed."); - + if (none) cmdlineP->compression = COMPRESSION_NONE; else if (packbits) @@ -216,7 +223,7 @@ parseCommandLine(int argc, cmdlineP->compression = COMPRESSION_DEFLATE; else cmdlineP->compression = COMPRESSION_NONE; - + if (msb2lsb + lsb2msb > 1) pm_error("You specified both -msb2lsb and -lsb2msb. " "These are conflicting options."); @@ -225,9 +232,9 @@ parseCommandLine(int argc, cmdlineP->fillorder = FILLORDER_MSB2LSB; else if (lsb2msb) cmdlineP->fillorder = FILLORDER_LSB2MSB; - else + else cmdlineP->fillorder = FILLORDER_MSB2LSB; - + if (cmdlineP->miniswhite && cmdlineP->minisblack) pm_error("You cannot specify both -miniswhite and -minisblack"); @@ -238,9 +245,17 @@ parseCommandLine(int argc, if (fill) cmdlineP->g3options |= GROUP3OPT_FILLBITS; + if (outputSpec) { + if (appendSpec) + cmdlineP->writeMethod = DIRECT_APPEND; + else + cmdlineP->writeMethod = DIRECT_CREATE; + } else + cmdlineP->writeMethod = TMPFILE; + if (predictorSpec) { if (cmdlineP->predictor != 1 && cmdlineP->predictor != 2) - pm_error("-predictor may be only 1 or 2. You specified %d.", + pm_error("-predictor may be only 1 or 2. You specified %d.", cmdlineP->predictor); } else cmdlineP->predictor = -1; @@ -318,13 +333,13 @@ parseCommandLine(int argc, cmdlineP->taglist[0].value = NULL; } - if (argc-1 == 0) - cmdlineP->input_filespec = "-"; + if (argc-1 == 0) + cmdlineP->inputFileName = "-"; else if (argc-1 != 1) pm_error("Program takes zero or one argument (filename). You " "specified %d", argc-1); else - cmdlineP->input_filespec = argv[1]; + cmdlineP->inputFileName = argv[1]; } @@ -346,9 +361,9 @@ fillRowOfSubBytePixels(struct pam * const pamP, int bitshift; /* The number of bits we have to shift a pixel value left to line it up with where the current pixel goes in the current byte of - the output buffer. + the output buffer. */ - int const firstbitshift = + int const firstbitshift = (fillorder == FILLORDER_MSB2LSB) ? 8 - bitspersample : 0; /* The value of 'bitshift' for the first pixel into a byte of the output buffer. (MSB2LSB is normal). @@ -363,7 +378,7 @@ fillRowOfSubBytePixels(struct pam * const pamP, /* The under-construction value of the byte pointed to by tP, above. */ - + bitshift = firstbitshift; byte = 0; for (col = 0, tP = buf; col < pamP->width; ++col) { @@ -372,7 +387,7 @@ fillRowOfSubBytePixels(struct pam * const pamP, s = tuplerow[col][0]; if (pamP->maxval != tiff_maxval ) s = (long) s * tiff_maxval / pamP->maxval; - + if (photometric == PHOTOMETRIC_MINISWHITE) s = tiff_maxval - s; } else { @@ -448,7 +463,7 @@ fillRowOfWholeBytePixels(struct pam * const pamP, unsigned int col; unsigned char * tP; unsigned int planes; - + if (photometric == PHOTOMETRIC_RGB) planes = pamP->depth; else @@ -465,18 +480,18 @@ fillRowOfWholeBytePixels(struct pam * const pamP, /* Advances tP */ } } -} +} static void writeScanLines(struct pam * const pamP, - TIFF * const tif, + TIFF * const tif, tuplehash const cht, unsigned short const tiffMaxval, - unsigned short const bitspersample, + unsigned short const bitspersample, unsigned short const photometric, - int const bytesperrow, + int const bytesperrow, int const fillorder) { /*---------------------------------------------------------------------------- Write out the raster for the input image described by 'pamP', whose @@ -510,7 +525,7 @@ writeScanLines(struct pam * const pamP, pm_error("can't allocate memory for row buffer"); tuplerow = pnm_allocpamrow(pamP); - + for (row = 0; row < pamP->height; ++row) { int col; @@ -532,9 +547,9 @@ writeScanLines(struct pam * const pamP, for (col = 0; col < pamP->width; ++col) { int si; int found; - + pnm_lookuptuple(pamP, cht, tuplerow[col], &found, &si); - + if (!found) pm_error("INTERNAL ERROR. We made a color map, and a " "color map we need is not in it! " @@ -558,12 +573,12 @@ writeScanLines(struct pam * const pamP, static void -analyzeColorsInRgbInput(struct pam * const pamP, - struct cmdlineInfo const cmdline, - int const maxcolors, - tupletable * const chvP, - unsigned int * const colorsP, - bool * const grayscaleP) { +analyzeColorsInRgbInput(struct pam * const pamP, + CmdlineInfo const cmdline, + int const maxcolors, + tupletable * const chvP, + unsigned int * const colorsP, + bool * const grayscaleP) { /*---------------------------------------------------------------------------- Same as analyzeColors(), except assuming input image has R/G/B tuples. -----------------------------------------------------------------------------*/ @@ -582,7 +597,7 @@ analyzeColorsInRgbInput(struct pam * const pamP, grayscale = FALSE; } else { unsigned int i; - pm_message("%u color%s found", + pm_message("%u color%s found", *colorsP, *colorsP == 1 ? "" : "s"); grayscale = TRUE; /* initial assumption */ for (i = 0; i < *colorsP && grayscale; ++i) { @@ -615,15 +630,15 @@ analyzeColorsInRgbInput(struct pam * const pamP, static void -analyzeColors(struct pam * const pamP, - struct cmdlineInfo const cmdline, - int const maxcolors, - tupletable * const chvP, - unsigned int * const colorsP, - bool * const grayscaleP) { +analyzeColors(struct pam * const pamP, + CmdlineInfo const cmdline, + int const maxcolors, + tupletable * const chvP, + unsigned int * const colorsP, + bool * const grayscaleP) { /*---------------------------------------------------------------------------- Analyze the colors in the input image described by 'pamP', whose file - is positioned to the raster. + is positioned to the raster. If the colors, combined with command line options 'cmdline', indicate a colormapped TIFF should be generated, return as *chvP the address @@ -652,13 +667,13 @@ analyzeColors(struct pam * const pamP, static void computeRasterParm(struct pam * const pamP, - tupletable const chv, - int const colors, + tupletable const chv, + int const colors, bool const grayscale, int const compression, bool const minisblack, bool const miniswhite, - struct sizeset const indexsizeAllowed, + SizeSet const indexsizeAllowed, unsigned short * const samplesperpixelP, unsigned short * const bitspersampleP, unsigned short * const photometricP, @@ -679,7 +694,7 @@ computeRasterParm(struct pam * const pamP, option. It is not clear why we don't use bits per pixel < 8 for RGB images. Note that code to handle maxvals <= 255 was written long before maxval > 255 was possible and there are - backward compatibility requirements. + backward compatibility requirements. */ if (pamP->depth == 1 && pamP->maxval == 1) { @@ -693,7 +708,7 @@ computeRasterParm(struct pam * const pamP, } else { if (chv) { *samplesperpixelP = 1; /* Pixel is just the one index value */ - *bitspersampleP = + *bitspersampleP = colors <= 2 && indexsizeAllowed.b1 ? 1 : colors <= 4 && indexsizeAllowed.b2 ? 2 : colors <= 16 && indexsizeAllowed.b4 ? 4 : @@ -746,18 +761,53 @@ computeRasterParm(struct pam * const pamP, -static void -validateSeekableOutputFile(int const ofd, - const char * const outFileName) { /*---------------------------------------------------------------------------- - Validate that the file attached to file descriptor 'ofd' is capable - of seeking. If not, fail the program. + WRITE MODES + ----------- + + The Tiff library does all output. There are several issues: + + 1) The manner of output is opaque to the library client. I.e. we cannot + see or control it. + + 2) The output file must be random-access. + + 3) The output file must be writable and readable for multiple-image + streams. (This includes append operations.) + + 4) The Tiff library produces unhelpful error messages when the above + conditions are not met. + + We provide two modes for output: + + 1. Tmpfile mode (default) + + We have the Tiff library direct output to an unnamed temporary file we + create which is seekable and readable. When output is complete, we copy + the file's contents to Standard Output. + + 2. Direct mode (specified with -output) + + We have the Tiff library write output to the specified file. As the Tiff + library requires taht it be be seekable and readable, we fail the program + rather than ask the Tiff library to use the file if it does not meet + these requirements. + + Direct mode is further divided into append and create. They are the same + except that in append mode, we insist that the file already exist, + whereas with create mode, we create it if necessary. In either case, if + the file already exists, he Tiff library appends the output to it. +-----------------------------------------------------------------------------*/ + + - This is useful because the TIFF library requires seekable output and - fails with an unhelpful error message about a file I/O error if it is - not. We, on the other hand, give a helpful error message. +static bool +fileIsSeekable(int const ofd, + const char * const outFileName) { +/*---------------------------------------------------------------------------- + The file represented by 'ofd' iscapable of seeking. - We leave the file positioned to the beginning. + As a side effect, we position the file to the beginning. -----------------------------------------------------------------------------*/ int rc; @@ -771,44 +821,160 @@ validateSeekableOutputFile(int const ofd, */ lseek(ofd, 1, SEEK_SET); rc = lseek(ofd, 0, SEEK_SET); - - if (rc < 0) - pm_error("Output file (%s) is not seekable. lseek() returned " - "errno %d (%s). " - "The TIFF library can write only to " - "a seekable file.", - outFileName, errno, strerror(errno)); + + return rc >= 0; + } static void -createTiffGenerator(int const ofd, - const char * const outFileName, - bool const append, - TIFF ** const tifPP) { +validateReadableOutputFile(int const ofd) { +/*---------------------------------------------------------------------------- + Validate that file 'ofd' is readable and fail the program if it isn't. - const char * option; + This is useful because there are situations in which the TIFF library must + read the output file and if it can't, it fails with an unhelpful error + message about a file I/O error. We, on the other hand, produce a helpful + error message. +-----------------------------------------------------------------------------*/ +#if !MSVCRT - validateSeekableOutputFile(ofd, outFileName); + int flags; - if (append) - option = "a"; + flags = fcntl(ofd, F_GETFL); + + if (flags < 0) { + /* We couldn't get the flags. So just assume the file's OK */ + } else { + if ((flags & O_RDONLY) || (flags & O_RDWR)) { + /* File is readable. All is well. */ + } else + pm_error("Output is not opened for reading. " + "In order to create a multi-image TIFF stream, " + "output must be both readable and writable."); + } +#endif +} + + + +static void +createTiffGeneratorDirect(const char * const outputFileName, + CreatePolicy const createPolicy, + TIFF ** const tifPP, + int * const ofdP) { +/*---------------------------------------------------------------------------- + Create a TIFF generator that writes its output to the specified file. + + If the file doesn't already exist and 'createPolicy' is MayCreate, + create the file; otherwise fail the program. + + Fail the program if the specified file is not seekable and readable. + + Return the handle of the TIFF generator as *tifPP. Also return the + file descriptor for the output file as *ofdP. +-----------------------------------------------------------------------------*/ + int fd; + + if (createPolicy == MUST_EXIST) + fd = open(outputFileName, O_RDWR); else - option = "w"; + fd = open(outputFileName, (O_RDWR | O_CREAT), 00644); + + if (fd == -1) { + if (errno == ENOENT) /* Possible only if MustExist */ + pm_error ("Cannot open file : '%s'. File does not exist.", + outputFileName); + else + pm_error ("Cannot open file : '%s'. open() failed with " + "errno %d (%s). ", + outputFileName, errno, strerror(errno)); + } - *tifPP = TIFFFdOpen(ofd, outFileName, option); + if (!fileIsSeekable(fd, outputFileName)) + pm_error("Output file (%s) is not seekable. " + "lseek() returned errno %d (%s). " + "The TIFF library can write only to " + "a seekable file.", + outputFileName, errno, strerror(errno)); + + *tifPP = TIFFFdOpen(fd, outputFileName, "a"); if (*tifPP == NULL) - pm_error("error opening standard output as TIFF file. " + pm_error("error opening file %s as TIFF file. " + "TIFFFdOpen() failed.", outputFileName); + + *ofdP = fd; +} + + + +static void +createTiffGeneratorTmpfile(TIFF ** const tifPP, + int * const ofdP) { +/*---------------------------------------------------------------------------- + Create a TIFF generator that writes its output to an unnnamed temporary file + we create. + + Return the handle of the TIFF generator as *tifPP. Also return the file + descriptor for the temporary file as *ofdP. + + The TIFF generator has a file name attribute, but it is just for messages; + it is not the name of a file. We use "Internal Temporary File". +-----------------------------------------------------------------------------*/ + int fd; + + fd = pm_tmpfile_fd(); + + *tifPP = TIFFFdOpen(fd, "Internal Temporary File", "w"); + + if (*tifPP == NULL) + pm_error("error opening temporary file as TIFF file. " "TIFFFdOpen() failed."); + + *ofdP = fd; +} + + + +static void +copyBufferToStdout(int const tmpfileFd) { + + FILE * tmpfileP; + + tmpfileP = fdopen(tmpfileFd, "rb"); + + fseek(tmpfileP, 0, SEEK_SET); + + while (!feof(tmpfileP) && !ferror(tmpfileP) && !ferror(stdout)) { + char buffer[4096]; + size_t bytesReadCt; + + bytesReadCt = fread(buffer, 1, sizeof(buffer), tmpfileP); + + if (ferror(tmpfileP)) + pm_error("Error reading from temporary file. " + "Incomplete output. " + "Errno = %s (%d)", strerror(errno), errno); + else + fwrite(buffer, 1, bytesReadCt, stdout); + } + + fclose(tmpfileP); } static void -destroyTiffGenerator(TIFF * const tifP) { +destroyTiffGenerator(WriteMethod const writeMethod, + TIFF * const tifP, + int const ofd) { TIFFFlushData(tifP); + + if (writeMethod == TMPFILE) + copyBufferToStdout(ofd); + TIFFClose(tifP); } @@ -825,11 +991,11 @@ createTiffColorMap(struct pam * const pamP, unsigned short ** tiffColorMap; unsigned int plane; unsigned int i; - + MALLOCARRAY_NOFAIL(tiffColorMap, pamP->depth); for (plane = 0; plane < pamP->depth; ++plane) MALLOCARRAY_NOFAIL(tiffColorMap[plane], colorMapSize); - + for (i = 0; i < colorMapSize; ++i) { unsigned int plane; for (plane = 0; plane < pamP->depth; ++plane) { @@ -842,7 +1008,7 @@ createTiffColorMap(struct pam * const pamP, } *tiffColorMapP = tiffColorMap; } - + static void @@ -867,7 +1033,7 @@ setTagListFields(const struct optNameValue * const taglist, for (i = 0; taglist[i].name; ++i) { const tagDefinition * const tagDefP = tagDefFind(taglist[i].name); - + if (tagDefP->put) tagDefP->put(tifP, tagDefP->tagnum, taglist[i].value, tagDefP->choices); @@ -878,7 +1044,7 @@ setTagListFields(const struct optNameValue * const taglist, static void setTiffFields(TIFF * const tifP, - struct cmdlineInfo const cmdline, + CmdlineInfo const cmdline, struct pam * const pamP, unsigned short const bitspersample, unsigned short const photometric, @@ -940,7 +1106,7 @@ setTiffFields(TIFF * const tifP, TIFFSetField(tifP, TIFFTAG_DOCUMENTNAME, inputFileDescription); TIFFSetField(tifP, TIFFTAG_IMAGEDESCRIPTION, "converted PNM file"); - + /* Some of taglist[] overrides defaults we set above. But taglist[] is defined not to specify any tag types that are not purely user choice. @@ -951,10 +1117,10 @@ setTiffFields(TIFF * const tifP, static void -convertImage(FILE * const ifP, - TIFF * const tifP, - const char * const inputFileDescription, - struct cmdlineInfo const cmdline) { +convertImage(FILE * const ifP, + TIFF * const tifP, + const char * const inputFileDescription, + CmdlineInfo const cmdline) { tupletable chv; tuplehash cht; @@ -966,7 +1132,7 @@ convertImage(FILE * const ifP, unsigned short samplesperpixel; unsigned short bitspersample; unsigned short tiff_maxval; - /* This is the maxval of the samples in the tiff file. It is + /* This is the maxval of the samples in the tiff file. It is determined solely by the bits per sample ('bitspersample'). */ int bytesperrow; @@ -979,11 +1145,11 @@ convertImage(FILE * const ifP, analyzeColors(&pam, cmdline, MAXCOLORS, &chv, &colors, &grayscale); /* Go back to beginning of raster */ - pm_seek2(ifP, &rasterPos, sizeof(rasterPos)); + pm_seek2(ifP, &rasterPos, sizeof(rasterPos)); /* Figure out TIFF parameters. */ - computeRasterParm(&pam, chv, colors, grayscale, + computeRasterParm(&pam, chv, colors, grayscale, cmdline.compression, cmdline.minisblack, cmdline.miniswhite, cmdline.indexsizeAllowed, @@ -1008,7 +1174,7 @@ convertImage(FILE * const ifP, cmdline.taglist); writeScanLines(&pam, tifP, cht, - tiff_maxval, bitspersample, photometric, bytesperrow, + tiff_maxval, bitspersample, photometric, bytesperrow, cmdline.fillorder); if (tiffColorMap) @@ -1017,63 +1183,41 @@ convertImage(FILE * const ifP, -static void -validateReadableStdout(void) { -/*---------------------------------------------------------------------------- - We validate that Standard Output is readable and fail the program if - it isn't. - - This is useful because there are situations in which the TIFF library - must read the output file and if it can't, it fails with an unhelpful - error message about a file I/O error. We, on the other hand, produce - a helpful error message. ------------------------------------------------------------------------------*/ -#if !MSVCRT - - int flags; - - flags = fcntl(STDOUT_FILENO, F_GETFL); - - if (flags < 0) { - /* We couldn't get the flags. So just assume the file's OK */ - } else { - if ((flags & O_RDONLY) || (flags & O_RDWR)) { - /* File is readable. All is well. */ - } else - pm_error("Standard Output is not opened for reading. " - "In order to create a multi-image TIFF stream, " - "Standard Output must be both readable and writable."); - } -#endif -} int -main(int argc, char *argv[]) { - struct cmdlineInfo cmdline; +main(int argc, const char *argv[]) { + CmdlineInfo cmdline; const char * inputFileDescription; - FILE* ifP; - TIFF* tifP; + FILE * ifP; + TIFF * tifP; + int ofd; int eof; unsigned int imageSeq; - - pnm_init(&argc, argv); - - parseCommandLine(argc, argv, &cmdline); - ifP = pm_openr_seekable(cmdline.input_filespec); + pm_proginit(&argc, argv); - if (streq(cmdline.input_filespec, "-")) - inputFileDescription = "Standard Input"; - else - inputFileDescription = cmdline.input_filespec; + parseCommandLine(argc, argv, &cmdline); - if (cmdline.append) - validateReadableStdout(); + ifP = pm_openr_seekable(cmdline.inputFileName); - createTiffGenerator(STDOUT_FILENO, "Standard Output", cmdline.append, - &tifP); + if (streq(cmdline.inputFileName, "-")) + inputFileDescription = "Standard Input"; + else + inputFileDescription = cmdline.inputFileName; + + switch (cmdline.writeMethod) { + case DIRECT_APPEND: + createTiffGeneratorDirect(cmdline.output, MUST_EXIST, &tifP, &ofd); + break; + case DIRECT_CREATE: + createTiffGeneratorDirect(cmdline.output, MAY_CREATE, &tifP, &ofd); + break; + case TMPFILE: + createTiffGeneratorTmpfile(&tifP, &ofd); + break; + } eof = FALSE; /* initial assumption */ imageSeq = 0; @@ -1081,17 +1225,17 @@ main(int argc, char *argv[]) { while (!eof) { bool success; - if (cmdline.verbose) - pm_message("Converting Image %u", imageSeq); - pnm_nextimage(ifP, &eof); if (!eof) { if (imageSeq > 0) - validateReadableStdout(); + validateReadableOutputFile(ofd); + + if (cmdline.verbose) + pm_message("Converting Image %u", imageSeq); convertImage(ifP, tifP, inputFileDescription, cmdline); - + success = TIFFWriteDirectory(tifP); if (!success) pm_error("Unable to write TIFF image %u to file. " @@ -1100,8 +1244,10 @@ main(int argc, char *argv[]) { } } - destroyTiffGenerator(tifP); + destroyTiffGenerator(cmdline.writeMethod, tifP, ofd); pm_close(ifP); return 0; } + + diff --git a/converter/other/pnmtopalm/Makefile b/converter/other/pnmtopalm/Makefile index 65790002..edc7da64 100644 --- a/converter/other/pnmtopalm/Makefile +++ b/converter/other/pnmtopalm/Makefile @@ -8,8 +8,10 @@ VPATH=.:$(SRCDIR)/$(SUBDIR) include $(BUILDDIR)/config.mk BINARIES = palmtopnm pnmtopalm +PORTBINARIES = $(BINARIES) gen_palm_colormap SCRIPTS = -OBJECTS = $(BINARIES:%=%.o) palmcolormap.o +ADDL_OBJECTS = palmcolormap.o +OBJECTS = $(BINARIES:%=%.o) $(ADDL_OBJECTS) gen_palm_colormap.o MERGE_OBJECTS = $(BINARIES:%=%.o2) palmcolormap.o MERGEBINARIES = $(BINARIES) DATAFILES = palmcolor8.map palmgray1.map palmgray2.map palmgray4.map @@ -18,17 +20,7 @@ all: $(BINARIES) include $(SRCDIR)/common.mk -LIBOPTS = $(shell $(LIBOPT) $(NETPBMLIB)) - -$(BINARIES): %: %.o palmcolormap.o $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ $< palmcolormap.o $(LIBOPTS) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(RPATH) $(LADD) - -gen_palm_colormap : % : %.c palmcolormap.o - $(CC) -I importinc $(CFLAGS_ALL) -o $@ \ - $< palmcolormap.o \ - $(LIBOPTS) $(MATHLIB) $(LDFLAGS) $(LDLIBS) $(LADD) - +$(BINARIES): $(ADDL_OBJECTS) clean: cleanspecial .PHONY: cleanspecial diff --git a/converter/other/pnmtopalm/gen_palm_colormap.c b/converter/other/pnmtopalm/gen_palm_colormap.c index c7172c6b..0f3f8a5f 100644 --- a/converter/other/pnmtopalm/gen_palm_colormap.c +++ b/converter/other/pnmtopalm/gen_palm_colormap.c @@ -3,8 +3,8 @@ * Based on an earlier version by Bill Janssen <bill@janssen.org> */ -#include "ppm.h" -#include "pm_c_util.h" +#include "netpbm/ppm.h" +#include "netpbm/pm_c_util.h" #include "palm.h" diff --git a/converter/other/pnmtosgi.c b/converter/other/pnmtosgi.c index 169125b3..a8df5328 100644 --- a/converter/other/pnmtosgi.c +++ b/converter/other/pnmtosgi.c @@ -31,17 +31,6 @@ typedef struct { long length; } ScanLine; -/* prototypes */ -static void put_big_short ARGS((short s)); -static void put_big_long ARGS((long l)); -#define put_byte(b) (void)(putc((unsigned char)(b), stdout)) -static void put_short_as_byte ARGS((short s)); -static void write_table ARGS((long *table, int tabsize)); -static void write_channels ARGS((int cols, int rows, int channels, void (*put) ARGS((short)) )); -static long * build_channels ARGS((FILE *ifp, int cols, int rows, xelval maxval, int format, int bpc, int channels)); -static ScanElem *compress ARGS((ScanElem *temp, int row, int rows, int cols, int chan_no, long *table, int bpc)); -static int rle_compress ARGS((ScanElem *inbuf, int cols)); - #define WORSTCOMPR(x) (2*(x) + 2) @@ -55,301 +44,348 @@ static ScanElem * rletemp; static xel * pnmrow; -static void -write_header(int const cols, - int const rows, - xelval const maxval, - int const bpc, - int const dimensions, - int const channels, - const char * const imagename) -{ - int i; - -#ifdef DEBUG - pm_message("writing header"); -#endif - - put_big_short(SGI_MAGIC); - put_byte(storage); - put_byte((char)bpc); - put_big_short(dimensions); - put_big_short(cols); - put_big_short(rows); - put_big_short(channels); - put_big_long(0); /* PIXMIN */ - put_big_long(maxval); /* PIXMAX */ - for( i = 0; i < 4; i++ ) - put_byte(0); - for( i = 0; i < 79 && imagename[i] != '\0'; i++ ) - put_byte(imagename[i]); - for(; i < 80; i++ ) - put_byte(0); - put_big_long(CMAP_NORMAL); - for( i = 0; i < 404; i++ ) - put_byte(0); -} +#define putByte(b) (void)(putc((unsigned char)(b), stdout)) -int -main(int argc,char * argv[]) -{ - FILE *ifp; - int argn; - const char * const usage = "[-verbatim|-rle] [-imagename <name>] [pnmfile]"; - int cols, rows, format; - xelval maxval, newmaxval; - const char *imagename = "no name"; - int bpc, dimensions, channels; - long *table = NULL; +static void +putBigShort(short const s) { - pnm_init(&argc, argv); + if (pm_writebigshort(stdout, s ) == -1) + pm_error( "write error" ); +} - argn = 1; - while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) { - if( pm_keymatch(argv[argn], "-verbatim", 2) ) - storage = STORAGE_VERBATIM; - else - if( pm_keymatch(argv[argn], "-rle", 2) ) - storage = STORAGE_RLE; - else - if( pm_keymatch(argv[argn], "-imagename", 2) ) { - if( ++argn >= argc ) - pm_usage(usage); - imagename = argv[argn]; - } - else - pm_usage(usage); - ++argn; - } - if( argn < argc ) { - ifp = pm_openr( argv[argn] ); - argn++; - } - else - ifp = stdin; - if( argn != argc ) - pm_usage(usage); +static void +putBigLong(long const l) { - pnm_readpnminit(ifp, &cols, &rows, &maxval, &format); - if( rows>INT16MAX || cols>INT16MAX ) - pm_error ("Input image is too large."); + if (pm_writebiglong( stdout, l ) == -1) + pm_error( "write error" ); +} - pnmrow = pnm_allocrow(cols); - switch( PNM_FORMAT_TYPE(format) ) { - case PBM_TYPE: - newmaxval = PGM_MAXMAXVAL; - pm_message("promoting PBM to PGM"); - case PGM_TYPE: - newmaxval = maxval; - dimensions = 2; channels = 1; - break; - case PPM_TYPE: - newmaxval = maxval; - dimensions = 3; channels = 3; - break; - default: - pm_error("can\'t happen"); - } - if( newmaxval <= MAXVAL_BYTE ) - bpc = 1; - else if( newmaxval <= MAXVAL_WORD ) - bpc = 2; - else - pm_error("maxval too large - try using \"pnmdepth %d\"", MAXVAL_WORD); - table = build_channels(ifp, cols, rows, newmaxval, format, bpc, channels); - pnm_freerow(pnmrow); - pm_close(ifp); - - write_header(cols, rows, newmaxval, bpc, dimensions, channels, imagename); - if( table ) - write_table(table, rows * channels); - if( bpc == 1 ) - write_channels(cols, rows, channels, put_short_as_byte); - else - write_channels(cols, rows, channels, put_big_short); +static void +putShortAsByte(short const s) { - exit(0); + putByte((unsigned char)s); } + static void -write_table(long * table, int const tabsize) -{ - int i; - long offset; +writeTable(long * const table, + unsigned int const tabsize) { -#ifdef DEBUG - pm_message("writing table"); -#endif + unsigned int i; + unsigned long offset; offset = HeaderSize + tabsize * 8; - for( i = 0; i < tabsize; i++ ) { - put_big_long(offset); + + for (i = 0; i < tabsize; ++i) { + putBigLong(offset); offset += table[i]; } - for( i = 0; i < tabsize; i++ ) - put_big_long(table[i]); + for (i = 0; i < tabsize; ++i) + putBigLong(table[i]); } + static void -write_channels(int const cols,int const rows, int const channels, - void (*put) (short)) -{ - int i, row, col; - -#ifdef DEBUG - pm_message("writing image data"); -#endif - - for( i = 0; i < channels; i++ ) { - for( row = 0; row < rows; row++ ) { - for( col = 0; col < channel[i][row].length; col++ ) { +writeChannels(unsigned int const cols, + unsigned int const rows, + unsigned int const channels, + void (*put) (short)) { + + unsigned int i; + + for (i = 0; i < channels; ++i) { + unsigned int row; + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < channel[i][row].length; ++col) { (*put)(channel[i][row].data[col]); } } } } -static void -put_big_short(short const s) -{ - if ( pm_writebigshort( stdout, s ) == -1 ) - pm_error( "write error" ); -} -static void -put_big_long(long const l) -{ - if ( pm_writebiglong( stdout, l ) == -1 ) - pm_error( "write error" ); +static int +rleCompress(ScanElem * const inbuf, + unsigned int const size) { + + /* slightly modified RLE algorithm from ppmtoilbm.c written by Robert + A. Knop (rknop@mop.caltech.edu) + */ + + int in, out, hold, count; + ScanElem *outbuf = rletemp; + + in = out = 0; + while (in < size) { + if ((in < size-1) && (inbuf[in] == inbuf[in+1])) { + /*Begin replicate run*/ + for (count = 0, hold = in; in < size && + inbuf[in] == inbuf[hold] && count < 127; + ++in, ++count) + ; + outbuf[out++] = (ScanElem)(count); + outbuf[out++] = inbuf[hold]; + } else { + /*Do a literal run*/ + hold = out; + ++out; + count = 0; + while (((in >= size-2) && (in < size)) + || ((in < size-2) && ((inbuf[in] != inbuf[in+1]) + || (inbuf[in] != inbuf[in+2])))) { + outbuf[out++] = inbuf[in++]; + if (++count >= 127) + break; + } + outbuf[hold] = (ScanElem)(count | 0x80); + } + } + outbuf[out++] = (ScanElem)0; /* terminator */ + + return out; } -static void -put_short_as_byte(short const s) -{ - put_byte((unsigned char)s); + +static ScanElem * +compress(ScanElem * const tempArg, + unsigned int const row, + unsigned int const rows, + unsigned int const cols, + unsigned int const chanNum, + long * const table, + unsigned int const bpc) { + + ScanElem * retval; + + switch (storage) { + case STORAGE_VERBATIM: + channel[chanNum][row].length = cols; + channel[chanNum][row].data = tempArg; + MALLOCARRAY_NOFAIL(retval, cols); + break; + case STORAGE_RLE: { + unsigned int const tabrow = chanNum * rows + row; + unsigned int const len = rleCompress(tempArg, cols); + /* writes result into rletemp */ + unsigned int i; + ScanElem * p; + + channel[chanNum][row].length = len; + MALLOCARRAY(p, len); + channel[chanNum][row].data = p; + for (i = 0; i < len; ++i) + p[i] = rletemp[i]; + table[tabrow] = len * bpc; + retval = tempArg; + } break; + default: + pm_error("unknown storage type - can't happen"); + } + return retval; } + static long * -build_channels(FILE * const ifp, int const cols, int const rows, - xelval const maxval, int const format, - int const bpc, int const channels) -{ - int i, row, col, sgirow; - long *table = NULL; - ScanElem *temp; - -#ifdef DEBUG - pm_message("building channels"); -#endif - - if( storage != STORAGE_VERBATIM ) { +buildChannels(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + xelval const maxval, + int const format, + unsigned int const bpc, + unsigned int const channels) { + + unsigned int row; + unsigned int sgirow; + long * table; + ScanElem * temp; + + if (storage != STORAGE_VERBATIM) { MALLOCARRAY_NOFAIL(table, channels * rows); MALLOCARRAY_NOFAIL(rletemp, WORSTCOMPR(cols)); - } + } else + table = NULL; + MALLOCARRAY_NOFAIL(temp, cols); - for( i = 0; i < channels; i++ ) - MALLOCARRAY_NOFAIL(channel[i], rows); + { + unsigned int i; + for (i = 0; i < channels; ++i) + MALLOCARRAY_NOFAIL(channel[i], rows); + } - for( row = 0, sgirow = rows-1; row < rows; row++, sgirow-- ) { - pnm_readpnmrow(ifp, pnmrow, cols, maxval, format); - if( channels == 1 ) { - for( col = 0; col < cols; col++ ) + for (row = 0, sgirow = rows-1; row < rows; ++row, --sgirow) { + pnm_readpnmrow(ifP, pnmrow, cols, maxval, format); + if (channels == 1) { + unsigned int col; + for (col = 0; col < cols; ++col) temp[col] = (ScanElem)PNM_GET1(pnmrow[col]); temp = compress(temp, sgirow, rows, cols, 0, table, bpc); - } - else { - for( col = 0; col < cols; col++ ) + } else { + unsigned int col; + for (col = 0; col < cols; ++col) temp[col] = (ScanElem)PPM_GETR(pnmrow[col]); temp = compress(temp, sgirow, rows, cols, 0, table, bpc); - for( col = 0; col < cols; col++ ) + for (col = 0; col < cols; ++col) temp[col] = (ScanElem)PPM_GETG(pnmrow[col]); temp = compress(temp, sgirow, rows, cols, 1, table, bpc); - for( col = 0; col < cols; col++ ) + for (col = 0; col < cols; ++col) temp[col] = (ScanElem)PPM_GETB(pnmrow[col]); temp = compress(temp, sgirow, rows, cols, 2, table, bpc); } } free(temp); - if( table ) + if (table) free(rletemp); return table; } -static ScanElem * -compress(ScanElem * temp, - int const row, int const rows, - int const cols, int const chan_no, - long * table, int const bpc) -{ - int len, i, tabrow; - ScanElem *p; - - switch( storage ) { - case STORAGE_VERBATIM: - channel[chan_no][row].length = cols; - channel[chan_no][row].data = temp; - MALLOCARRAY_NOFAIL(temp, cols); + +static void +writeHeader(unsigned int const cols, + unsigned int const rows, + xelval const maxval, + unsigned int const bpc, + unsigned int const dimensions, + unsigned int const channels, + const char * const imagename) { + + unsigned int i; + + putBigShort(SGI_MAGIC); + putByte(storage); + putByte((char)bpc); + putBigShort(dimensions); + putBigShort(cols); + putBigShort(rows); + putBigShort(channels); + putBigLong(0); /* PIXMIN */ + putBigLong(maxval); /* PIXMAX */ + + for(i = 0; i < 4; ++i) + putByte(0); + + for (i = 0; i < 79 && imagename[i] != '\0'; ++i) + putByte(imagename[i]); + + for(; i < 80; ++i) + putByte(0); + + putBigLong(CMAP_NORMAL); + + for (i = 0; i < 404; ++i) + putByte(0); +} + + + +int +main(int argc,char * argv[]) { + + FILE * ifP; + int argn; + const char * const usage = "[-verbatim|-rle] [-imagename <name>] [pnmfile]"; + int cols, rows; + int format; + xelval maxval, newmaxval; + const char * imagename; + unsigned int bpc; + unsigned int dimensions; + unsigned int channels; + long * table; + + pnm_init(&argc, argv); + + imagename = "no name"; /* default value */ + argn = 1; + while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) { + if( pm_keymatch(argv[argn], "-verbatim", 2) ) + storage = STORAGE_VERBATIM; + else + if( pm_keymatch(argv[argn], "-rle", 2) ) + storage = STORAGE_RLE; + else + if( pm_keymatch(argv[argn], "-imagename", 2) ) { + if( ++argn >= argc ) + pm_usage(usage); + imagename = argv[argn]; + } + else + pm_usage(usage); + ++argn; + } + + if( argn < argc ) { + ifP = pm_openr( argv[argn] ); + argn++; + } + else + ifP = stdin; + + if( argn != argc ) + pm_usage(usage); + + pnm_readpnminit(ifP, &cols, &rows, &maxval, &format); + + if (rows > INT16MAX || cols > INT16MAX) + pm_error ("Input image is too large."); + + pnmrow = pnm_allocrow(cols); + + switch (PNM_FORMAT_TYPE(format)) { + case PBM_TYPE: + pm_message("promoting PBM to PGM"); + newmaxval = PGM_MAXMAXVAL; + case PGM_TYPE: + newmaxval = maxval; + dimensions = 2; + channels = 1; break; - case STORAGE_RLE: - tabrow = chan_no * rows + row; - len = rle_compress(temp, cols); /* writes result into rletemp */ - channel[chan_no][row].length = len; - MALLOCARRAY(p, len); - channel[chan_no][row].data = p; - for( i = 0; i < len; i++, p++ ) - *p = rletemp[i]; - table[tabrow] = len * bpc; + case PPM_TYPE: + newmaxval = maxval; + dimensions = 3; + channels = 3; break; default: - pm_error("unknown storage type - can\'t happen"); + pm_error("can\'t happen"); } - return temp; -} + if (newmaxval <= MAXVAL_BYTE) + bpc = 1; + else if (newmaxval <= MAXVAL_WORD) + bpc = 2; + else + pm_error("maxval too large - try using \"pnmdepth %u\"", MAXVAL_WORD); + table = buildChannels(ifP, cols, rows, newmaxval, format, bpc, channels); -/* -slightly modified RLE algorithm from ppmtoilbm.c -written by Robert A. Knop (rknop@mop.caltech.edu) -*/ -static int -rle_compress(ScanElem * const inbuf, int const size) -{ - int in, out, hold, count; - ScanElem *outbuf = rletemp; + pnm_freerow(pnmrow); - in=out=0; - while( in<size ) { - if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) { /*Begin replicate run*/ - for( count=0,hold=in; in<size && inbuf[in]==inbuf[hold] && count<127; in++,count++) - ; - outbuf[out++]=(ScanElem)(count); - outbuf[out++]=inbuf[hold]; - } - else { /*Do a literal run*/ - hold=out; out++; count=0; - while( ((in>=size-2)&&(in<size)) || ((in<size-2) && ((inbuf[in]!=inbuf[in+1])||(inbuf[in]!=inbuf[in+2]))) ) { - outbuf[out++]=inbuf[in++]; - if( ++count>=127 ) - break; - } - outbuf[hold]=(ScanElem)(count | 0x80); - } - } - outbuf[out++] = (ScanElem)0; /* terminator */ - return(out); + pm_close(ifP); + + writeHeader(cols, rows, newmaxval, bpc, dimensions, channels, imagename); + + if (table) + writeTable(table, rows * channels); + + if (bpc == 1) + writeChannels(cols, rows, channels, putShortAsByte); + else + writeChannels(cols, rows, channels, putBigShort); + + return 0; } + diff --git a/converter/other/sgi.h b/converter/other/sgi.h index 3700d356..2f57f52d 100644 --- a/converter/other/sgi.h +++ b/converter/other/sgi.h @@ -5,7 +5,7 @@ typedef struct { short magic; - char storage; + unsigned char storage; char bpc; /* pixel size: 1 = bytes, 2 = shorts */ unsigned short dimension; /* 1 = single row, 2 = B/W, 3 = RGB */ unsigned short xsize, /* width in pixels */ @@ -25,9 +25,9 @@ typedef struct { #define STORAGE_RLE 1 #define CMAP_NORMAL 0 -#define CMAP_DITHERED 1 /* not supported */ -#define CMAP_SCREEN 2 /* not supported */ -#define CMAP_COLORMAP 3 /* not supported */ +#define CMAP_DITHERED 1 /* can't handle this */ +#define CMAP_SCREEN 2 /* can't handle this */ +#define CMAP_COLORMAP 3 /* can't handle this */ #endif diff --git a/converter/other/sgitopnm.c b/converter/other/sgitopnm.c index ea2daef3..008d5376 100644 --- a/converter/other/sgitopnm.c +++ b/converter/other/sgitopnm.c @@ -5,6 +5,11 @@ ** Based on the SGI image description v0.9 by Paul Haeberli (paul@sgi.comp) ** Available via ftp from sgi.com:graphics/SGIIMAGESPEC ** +** The definitive document describing the SGI image file format, +** SGI Image File Format Version 1.00 is available from +** ftp://ftp.sgi.com/graphics/grafica/sgiimage.html +** +** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that @@ -12,12 +17,9 @@ ** documentation. This software is provided "as is" without express or ** implied warranty. ** -** 29Jan94: first version -** 08Feb94: minor bugfix -** 29Jul00: added -channel option (smar@reptiles.org) -** 19Oct10: added checks for artihmetic overflows -** fixed problem with -channel on verbatim sgi images (afu) */ + + #include <unistd.h> #include <limits.h> #include "pm_c_util.h" @@ -28,12 +30,12 @@ -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char * inputFileName; /* '-' if stdin */ - unsigned int verbose; + const char * inputFileName; /* '-' if stdin */ + unsigned int verbose; unsigned int channelSpec; unsigned int channel; }; @@ -42,10 +44,10 @@ struct cmdlineInfo { static void parseCommandLine(int argc, const char ** argv, - struct cmdlineInfo * const cmdlineP) { + struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. + and argv. Return the information in the options as *cmdlineP. If command line is internally inconsistent (invalid options, etc.), issue error message to stderr and abort program. @@ -53,7 +55,7 @@ parseCommandLine(int argc, const char ** argv, Note that the strings we return are stored in the storage that was passed to us as the argv array. We also trash *argv. -----------------------------------------------------------------------------*/ - optEntry *option_def; + optEntry * option_def; /* Instructions to pm_optParseOptions3 on how to parse our options. */ optStruct3 opt; @@ -68,7 +70,7 @@ parseCommandLine(int argc, const char ** argv, &cmdlineP->channelSpec, 0); OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); - OPTENT3(0, "noverbose", OPT_FLAG, NULL, + OPTENT3(0, "noverbose", OPT_FLAG, NULL, NULL, 0); /* backward compatibility */ opt.opt_table = option_def; @@ -78,6 +80,8 @@ parseCommandLine(int argc, const char ** argv, pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + free(option_def); + if (argc-1 < 1) cmdlineP->inputFileName = "-"; else if (argc-1 == 1) @@ -165,9 +169,9 @@ getByteAsShort(FILE * const ifP) { static const char * -compressionName(char const compr) { +compressionName(unsigned char const storageCode) { - switch (compr) { + switch (storageCode) { case STORAGE_VERBATIM: return "none"; case STORAGE_RLE: @@ -214,7 +218,7 @@ readHeader(FILE * const ifP, headP->pixmin = getBigLong(ifP); headP->pixmax = getBigLong(ifP); if (headP->pixmin >= headP->pixmax) - pm_error("Invalid sgi image header: pixmin larger than pixmax"); + pm_error("Invalid sgi image header: pixmin larger than pixmax"); readBytes(ifP, 4, headP->dummy1); readBytes(ifP, 80, headP->name); headP->colormap = getBigLong(ifP); @@ -243,26 +247,32 @@ readHeader(FILE * const ifP, headP->dimension = 2; break; case 2: - pm_error("don't know how to interpret 2-channel image"); + if (!outChannelSpec) + pm_message("2-channel image, using only first channel. " + "Extract alpha channel with -channel=1"); break; case 3: break; default: if (!outChannelSpec) - pm_message("%d-channel image, using only first 3 channels", - headP->zsize); + pm_message("%u-channel image, using only first 3 channels " + "Extract %s with -channel=%c", + headP->zsize, + headP->zsize==4 ? + "alpha channel" : "additional channels", + headP->zsize==4 ? '3' : 'N'); break; } break; default: - pm_error("illegal dimension value %d (only 1-3 allowed)", + pm_error("illegal dimension value %u (only 1-3 allowed)", headP->dimension); } if (verbose) { - pm_message("raster size %dx%d, %d channels", + pm_message("raster size %ux%u, %u channels", headP->xsize, headP->ysize, headP->zsize); - pm_message("compression: %d = %s", + pm_message("compression: 0x%02x = %s", headP->storage, compressionName(headP->storage)); headP->name[79] = '\0'; /* just to be safe */ pm_message("Image name: '%s'", headP->name); @@ -345,7 +355,7 @@ rleDecompress(ScanElem * const srcStart, static ScanLine * readChannels(FILE * const ifP, Header * const head, - TabEntry * const table, + TabEntry * const table, bool const outChannelSpec, unsigned int const outChannel) { @@ -357,11 +367,14 @@ readChannels(FILE * const ifP, if (outChannelSpec) { maxchannel = outChannel + 1; MALLOCARRAY_NOFAIL(image, head->ysize); + } else if (head->zsize <= 2) { + maxchannel = 1; + MALLOCARRAY_NOFAIL(image, head->ysize); } else { - maxchannel = MIN(3, head->zsize); + maxchannel = 3; MALLOCARRAY_NOFAIL(image, head->ysize * maxchannel); } - if (table) + if (table) MALLOCARRAY_NOFAIL(temp, WORSTCOMPR(head->xsize)); for (channel = 0; channel < maxchannel; ++channel) { @@ -377,16 +390,17 @@ readChannels(FILE * const ifP, if (table) { if (!outChannelSpec || channel >= outChannel) { - long const offset = table[sgiIndex].start; + pm_filepos const offset = (pm_filepos) + table[sgiIndex].start; long const length = head->bpc == 2 ? table[sgiIndex].length / 2 : table[sgiIndex].length; unsigned int i; - /* doc says length is in bytes, we are reading words */ - if (fseek(ifP, offset, SEEK_SET) != 0) - pm_error("seek error for offset %ld", offset); + /* Note: (offset < currentPosition) can happen */ + + pm_seek2(ifP, &offset, sizeof(offset)); for (i = 0; i < length; ++i) if (head->bpc == 1) @@ -404,7 +418,7 @@ readChannels(FILE * const ifP, else p = getBigShort(ifP); - if (channel == outChannel || !outChannelSpec) + if (!outChannelSpec || outChannel == channel) image[iindex][i] = p; } } @@ -430,7 +444,7 @@ imageToPnm(Header * const head, int row; int format; - if (head->zsize == 1 || outChannelSpec) { + if (head->zsize <= 2 || outChannelSpec) { pm_message("writing PGM image"); format = PGM_TYPE; } else { @@ -459,10 +473,10 @@ imageToPnm(Header * const head, -int +int main(int argc, const char * argv[]) { - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; FILE * ifP; TabEntry * table; ScanLine * image; @@ -472,8 +486,8 @@ main(int argc, const char * argv[]) { pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); - - ifP = pm_openr(cmdline.inputFileName); + + ifP = pm_openr_seekable(cmdline.inputFileName); headP = readHeader(ifP, cmdline.channelSpec, cmdline.verbose); @@ -491,14 +505,14 @@ main(int argc, const char * argv[]) { table = readTable(ifP, headP->ysize * headP->zsize); else table = NULL; - + image = readChannels(ifP, headP, table, cmdline.channelSpec, cmdline.channel); imageToPnm(headP, image, maxval, cmdline.channelSpec, cmdline.channel); pm_close(ifP); - + return 0; } diff --git a/converter/other/tifftopnm.c b/converter/other/tifftopnm.c index fcfb03f6..214c02aa 100644 --- a/converter/other/tifftopnm.c +++ b/converter/other/tifftopnm.c @@ -1457,7 +1457,7 @@ convertRasterInMemory(pnmOut * const pnmOutP, int ok; ok = TIFFRGBAImageOK(tif, emsg); if (!ok) { - pm_message(emsg); + pm_message("%s", emsg); *statusP = CONV_UNABLE; } else { uint32 * raster; @@ -1477,14 +1477,14 @@ convertRasterInMemory(pnmOut * const pnmOutP, ok = TIFFRGBAImageBegin(&img, tif, stopOnErrorFalse, emsg); if (!ok) { - pm_message(emsg); + pm_message("%s", emsg); *statusP = CONV_FAILED; } else { int ok; ok = TIFFRGBAImageGet(&img, raster, cols, rows); TIFFRGBAImageEnd(&img) ; if (!ok) { - pm_message(emsg); + pm_message("%s", emsg); *statusP = CONV_FAILED; } else { *statusP = CONV_DONE; |