From 1fd361a1ea06e44286c213ca1f814f49306fdc43 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 19 Aug 2006 03:12:28 +0000 Subject: Create Subversion repository git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/other/jbig/ANNOUNCE | 243 +++ converter/other/jbig/Makefile | 47 + converter/other/jbig/README.Netpbm | 12 + converter/other/jbig/jbig.c | 2905 ++++++++++++++++++++++++++++++++++++ converter/other/jbig/jbig.doc | 721 +++++++++ converter/other/jbig/jbig.h | 267 ++++ converter/other/jbig/jbig_tab.c | 428 ++++++ converter/other/jbig/jbigtopnm.c | 286 ++++ converter/other/jbig/pnmtojbig.c | 463 ++++++ 9 files changed, 5372 insertions(+) create mode 100644 converter/other/jbig/ANNOUNCE create mode 100644 converter/other/jbig/Makefile create mode 100644 converter/other/jbig/README.Netpbm create mode 100644 converter/other/jbig/jbig.c create mode 100644 converter/other/jbig/jbig.doc create mode 100644 converter/other/jbig/jbig.h create mode 100644 converter/other/jbig/jbig_tab.c create mode 100644 converter/other/jbig/jbigtopnm.c create mode 100644 converter/other/jbig/pnmtojbig.c (limited to 'converter/other/jbig') diff --git a/converter/other/jbig/ANNOUNCE b/converter/other/jbig/ANNOUNCE new file mode 100644 index 00000000..edbcc3f8 --- /dev/null +++ b/converter/other/jbig/ANNOUNCE @@ -0,0 +1,243 @@ + +Version 1.2 of the JBIG-KIT lossless image compression library available +------------------------------------------------------------------------ + +Markus Kuhn -- 2000-04-08 + + +The latest release of JBIG-KIT can be downloaded over the Internet +with anonymous ftp from + + ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/JBIG/jbigkit-1.2.tar.gz + http://www.cl.cam.ac.uk/~mgk25/download/jbigkit-1.2.tar.gz + +and from a number of other servers. + +JBIG-KIT implements a highly effective data compression algorithm for +bi-level high-resolution images such as fax pages or scanned +documents. + +JBIG-KIT provides a portable library of compression and decompression +functions with a documented interface that you can very easily include +into your image or document processing software. In addition, JBIG-KIT +provides ready-to-use compression and decompression programs with a +simple command line interface (similar to the converters found in Jef +Poskanzer's PBM graphics file conversion package). + +JBIG-KIT implements the specification + + International Standard ISO/IEC 11544:1993 and ITU-T Recommendation + T.82(1993), "Information technology - Coded representation of picture + and audio information - progressive bi-level image compression", + , + +which is commonly referred to as the "JBIG standard". JBIG (Joint +Bi-level Image experts Group) is the committee which developed this +international standard for the lossless compression of images using +arithmetic coding. Like the well-known compression algorithms JPEG and +MPEG, also JBIG has been developed and published by the International +Organization for Standardization (ISO) and the International +Telecommunication Union (ITU). See also + + http://www.jpeg.org/public/jbighomepage.htm + http://www.iso.ch/ + http://www.itu.ch/ + +The JBIG compression algorithm offers the following features: + + - Close to state-of-the-art lossless compression ratio for high + resolution bi-level images. + + - Around 1.1 to 1.5 times better compression ratio on typical + scanned documents compared to G4 fax compression (ITU-T T.6), + which has been the best compression algorithm for scanned + documents available prior to JBIG. + + - Up to 30 times better compression of scanned images with dithered + images compared to G4 fax compression. + + - Around 2 times better compression on typical 300 dpi documents + compared to 'gzip -9' on raw bitmaps. + + - Around 3-4 times better compression than GIF on typical 300 dpi + documents. + + - Even much better competitive compression results on computer + generated images which are free of scanning distortions. + + - JBIG supports hierarchical "progressive" encoding, that means it is + possible to encode a low resolution image first, followed by + resolution enhancement data. This allows for instance a document + browser to display already a good 75 dpi low resolution version of + an image, while the data necessary to reconstruct the full 300 dpi + version for laser printer reproduction is still arriving (say + over a slow network link or mass storage medium). + + - The various resolution layers of a JBIG image in progressive + encoding mode together require not much more space than a + normal non-progressive mode encoded image (which JBIG also + supports). + + - The progressive encoding mode utilizes a very sophisticated + resolution reduction algorithm which offers highest quality + low resolution versions that preserve the shape of characters as + well as the integrity of thin lines and dithered images. + + - JBIG supports multiple bit planes and can this way also be used + for greyscale and color images, although the main field of + application is compression of bi-level images, i.e. images with + only two different pixel values. For greyscale images with up to + 6 bit per pixel, JBIG performs superior to JPEG's lossless + mode. + +JBIG-KIT is free software under the GNU General Public License. For +other license arrangements contact the author. JBIG-KIT provides a +portable library implemented in ANSI/ISO C for encoding and decoding +JBIG data streams together with documentation. The library is not +intended for 8-bit or 16-bit machine architectures (e.g., old MS-DOS C +compilers) on which a number of very efficient optimization techniques +used in this software are not possible. For maximum performance, a +32-bit processor is required (64-bit systems work too, of course). On +architectures with 16-bit pointer arithmetic, only very small images +can be processed. + +Special features of the JBIG-KIT implementation are: + + - Fully reentrant multithread-capable design (no global or static + variables, isolated malloc()/free() calls, etc.). + + - Capable of handling incomplete and growing JBIG data streams in + order to allow earliest display of low resolution versions. + + - Capable of handling several incoming data streams simultaneously + in one single process and task. + + - Especially designed with applications in mind that want to display + incoming data as early as possible (e.g., similar to the way in + which Netscape Navigator handles incoming GIF images). + + - Implements all JBIG features and options including progressive and + sequential encoding, multiple bit planes, user specified + resolution reduction and deterministic prediction tables, adaptive + template changes for optimal performance on half-tone images, + deterministic prediction, typical prediction in lowest and + differential layers, various stripe orderings, etc. Only the SEQ + and HITOLO options are currently not supported by the decoder + (they are normally never required, but could be added later in + case of user requirements). + + - Efficient code, optimized utilization of 32-bit processor + registers. + + - Very easy to use documented C library interface. + + - Included Gray code conversion routines for efficient encoding + of greyscale images. + + - Ready-to-use pbmtojbg and jbgtopbm converters. + + +Changes in version 1.2 (2000-04-08): + + - bug in the decoder fixed, which caused the rest of the input file + to be skipped whenever a comment marker was encountered (special + thanks to Ben Rudiak-Gould for + reporting this one) + +Changes in version 1.1 (1999-11-16): + + - serious bug in the encoder fixed, which for a very small + percentage of images has caused an unterminated linked list to be + created internally that could have been responsible for + segmentation violations or non-terminating encoders + (special thanks to Hisashi Saiga for + tracking that one down) + + - minor bug in the "jbgtopbm -d" diagnostic output fixed + +Changes in version 1.0 (1998-04-11): + + - two bugs fixed that caused the encoder and decoder to fail + under certain modes of operation with several bit planes + + - added new functions jbg_split_planes(), jbg_dec_merge_planes(), + and jbg_dec_getsize_merged() for easy handling of greyscale + images + + - added support for compressing greyscale PGM files to pbmtojbg + and jbgtopbm + + - more changes to avoid paranoid compiler warnings + +Changes in version 0.9 (1996-01-09): + + - encoder won't break any more on input bitmap data with incorrect + zero padding + + - pbmtojbg displays a warning if input file has incorrect zero + padding + + - various minor improvements suggested by Stefan Willer + + + - many minor changes in order to avoid warnings from paranoid + compilers + +Changes in version 0.8 (1995-09-20): + + - namespace cleared up, all names externally visible from the library + start now with jbg_ or JBG_ + + - minor non-critical bug fixed which caused library to fail compatibility + test and showed up especially on DEC Alpha systems + + - jbg_dec_gethight() is now called jbg_dec_getheight() + + - filenames conform now to MS-DOS limits + + - Bug in pbmtojbg fixed (handling of ASCII PBM files) + +Changes in version 0.7 (1995-06-10): + + - more problems on 16-bit int systems and on Macintosh systems fixed + (special thanks to Jean-Pierre Gachen ) + + - global Makefile + +Changes in version 0.6 (1995-06-08): + + - memory leak fixed + + - should now also work on systems where int is only 16-bit large + + - changes of the JBIG "Technical Corrigendum 1" included (special + thanks to Dr. Sebestyen from Siemens AG for sending me a copy + of the draft) + +First release: version 0.5 (1995-05-28) + + +Please send all questions, problem reports, patches, suggestions, +success stories, comments, etc. to + + mkuhn at acm.org + +I will try to provide free support and maintenance for this software +at least for the next few months depending on my available time. + +Y2K statement: JBIG-KIT does not handle any date and time related +data, therefore if JBIG-KIT causes you any problems related to date +and time overflows, this would indeed be most surprising. + +This library has been published in the hope that it will encourage the +development of good freely available scanned document handling and +transmission systems for the Internet so that large amounts of scanned +text can be made available to the global village easily. + +Happy compressing ... + +Markus Kuhn + +-- +Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK +email: mkuhn at acm.org, home page: diff --git a/converter/other/jbig/Makefile b/converter/other/jbig/Makefile new file mode 100644 index 00000000..ca98ef29 --- /dev/null +++ b/converter/other/jbig/Makefile @@ -0,0 +1,47 @@ +ifeq ($(SRCDIR)x,x) + SRCDIR = $(CURDIR)/../../.. + BUILDDIR = $(SRCDIR) +endif +SUBDIR = converter/other/jbig +VPATH=.:$(SRCDIR)/$(SUBDIR) + +include $(BUILDDIR)/Makefile.config + +LIBJBIG_OBJECTS = jbig.o jbig_tab.o + +INCLUDES = +ifneq ($(JBIGHDR_DIR),NONE) + INCLUDES += -I$(JBIGHDR_DIR) +endif + +ifneq ($(JBIGHDR_DIR),NONE) + ifneq ($(JBIGLIB),NONE) + BINARIES = jbigtopnm pnmtojbig + endif +endif + +SCRIPTS = + +ifeq ($(JBIGLIB),$(BUILDDIR)/$(SUBDIR)/libjbig.a) + 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) + +all: $(BINARIES) + +include $(SRCDIR)/Makefile.common + +$(BINARIES): %: %.o $(JBIGLIB_DEP) $(NETPBMLIB) $(LIBOPT) + $(LD) $(LDFLAGS) -o $@ $< \ + $(shell $(LIBOPT) $(NETPBMLIB) $(JBIGLIB)) $(MATHLIB) $(LDLIBS) \ + $(RPATH) $(LADD) + + +$(BUILDDIR)/$(SUBDIR)/libjbig.a: $(LIBJBIG_OBJECTS) + $(AR) -rc $@ $^ + $(RANLIB) $@ + diff --git a/converter/other/jbig/README.Netpbm b/converter/other/jbig/README.Netpbm new file mode 100644 index 00000000..3d593b92 --- /dev/null +++ b/converter/other/jbig/README.Netpbm @@ -0,0 +1,12 @@ +The jbig tools are derived from the JBIG-KIT package by Marcus Kuhn, +by Bryan Henderson on 2000.05.11. + +The file ANNOUNCE in this directory is from that package and gives +details. + +The Netpbm tools jbigtopbm and pbmtojbig were adapted from JBIG-KIT's +jbgtopbm and pbmtojbg. The main difference is that the Netpbm +versions use the Netpbm libraries. + +The jbig.c and jbig_table.c modules are straight from the JBIG_KIT +package. They are what normally are packaged as libjbig.a. diff --git a/converter/other/jbig/jbig.c b/converter/other/jbig/jbig.c new file mode 100644 index 00000000..ebd7c08f --- /dev/null +++ b/converter/other/jbig/jbig.c @@ -0,0 +1,2905 @@ +/* + * Portable Free JBIG image compression library + * + * Markus Kuhn -- mkuhn@acm.org + * + * $Id: jbig.c,v 1.12 2000-04-08 11:42:18+01 mgk25 Rel $ + * + * This module implements a portable standard C encoder and decoder + * using the JBIG lossless bi-level image compression algorithm as + * specified in International Standard ISO 11544:1993 or equivalently + * as specified in ITU-T Recommendation T.82. See the file jbig.doc + * for usage instructions and application examples. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * If you want to use this program under different license conditions, + * then contact the author for an arrangement. + * + * It is possible that certain products which can be built using this + * software module might form inventions protected by patent rights in + * some countries (e.g., by patents about arithmetic coding algorithms + * owned by IBM and AT&T in the USA). Provision of this software by the + * author does NOT include any licences for any patents. In those + * countries where a patent licence is required for certain applications + * of this software module, you will have to obtain such a licence + * yourself. + */ + +#ifdef DEBUG +#include +#endif + +#include +#include + +#include "jbig.h" + + +/* optional export of arithmetic coder functions for test purposes */ +#ifdef TEST_CODEC +#define ARITH +#define ARITH_INL +#else +#define ARITH static +#ifdef __GNUC__ +#define ARITH_INL static __inline__ +#else +#define ARITH_INL static +#endif +#endif + +#define MX_MAX 23 /* maximal supported mx offset for + * adaptive template in the encoder */ + +#define TPB2CX 0x195 /* contexts for TP special pixels */ +#define TPB3CX 0x0e5 +#define TPDCX 0xc3f + +/* marker codes */ +#define MARKER_STUFF 0x00 +#define MARKER_RESERVE 0x01 +#define MARKER_SDNORM 0x02 +#define MARKER_SDRST 0x03 +#define MARKER_ABORT 0x04 +#define MARKER_NEWLEN 0x05 +#define MARKER_ATMOVE 0x06 +#define MARKER_COMMENT 0x07 +#define MARKER_ESC 0xff + +/* loop array indices */ +#define STRIPE 0 +#define LAYER 1 +#define PLANE 2 + +/* special jbg_buf pointers (instead of NULL) */ +#define SDE_DONE ((struct jbg_buf *) -1) +#define SDE_TODO ((struct jbg_buf *) 0) + +/* object code version id */ + +const char jbg_version[] = +" JBIG-KIT " JBG_VERSION " -- Markus Kuhn -- " +"$Id: jbig.c,v 1.12 2000-04-08 11:42:18+01 mgk25 Rel $ "; + +/* + * the following array specifies for each combination of the 3 + * ordering bits, which ii[] variable represents which dimension + * of s->sde. + */ +static const int index[8][3] = { + { 2, 1, 0 }, /* no ordering bit set */ + { -1, -1, -1}, /* SMID -> illegal combination */ + { 2, 0, 1 }, /* ILEAVE */ + { 1, 0, 2 }, /* SMID + ILEAVE */ + { 0, 2, 1 }, /* SEQ */ + { 1, 2, 0 }, /* SEQ + SMID */ + { 0, 1, 2 }, /* SEQ + ILEAVE */ + { -1, -1, -1 } /* SEQ + SMID + ILEAVE -> illegal combination */ +}; + + +/* + * Array [language][message] with text string error messages that correspond + * to return values from public functions in this library. + */ +#define NEMSG 9 /* number of error codes */ +#define NEMSG_LANG 3 /* number of supported languages */ +static const char *errmsg[NEMSG_LANG][NEMSG] = { + /* English (JBG_EN) */ + { + "Everything is ok", /* JBG_EOK */ + "Reached specified maximum size", /* JBG_EOK_INTR */ + "Unexpected end of data", /* JBG_EAGAIN */ + "Not enough memory available", /* JBG_ENOMEM */ + "ABORT marker found", /* JBG_EABORT */ + "Unknown marker segment encountered", /* JBG_EMARKER */ + "Incremental BIE does not fit to previous one", /* JBG_ENOCONT */ + "Invalid data encountered", /* JBG_EINVAL */ + "Unimplemented features used" /* JBG_EIMPL */ + }, + /* German (JBG_DE_8859_1) */ + { + "Kein Problem aufgetreten", /* JBG_EOK */ + "Angegebene maximale Bildgr\366\337e erreicht", /* JBG_EOK_INTR */ + "Unerwartetes Ende der Daten", /* JBG_EAGAIN */ + "Nicht gen\374gend Speicher vorhanden", /* JBG_ENOMEM */ + "Es wurde eine Abbruch-Sequenz gefunden", /* JBG_EABORT */ + "Eine unbekannte Markierungssequenz wurde gefunden", /* JBG_EMARKER */ + "Neue Daten passen nicht zu vorangegangenen Daten", /* JBG_ENOCONT */ + "Es wurden ung\374ltige Daten gefunden", /* JBG_EINVAL */ + "Noch nicht implementierte Optionen wurden benutzt" /* JBG_EIMPL */ + }, + /* German (JBG_DE_UTF_8) */ + { + "Kein Problem aufgetreten", /* JBG_EOK */ + "Angegebene maximale Bildgr\303\266\303\237e erreicht", /* JBG_EOK_INTR */ + "Unerwartetes Ende der Daten", /* JBG_EAGAIN */ + "Nicht gen\303\274gend Speicher vorhanden", /* JBG_ENOMEM */ + "Es wurde eine Abbruch-Sequenz gefunden", /* JBG_EABORT */ + "Eine unbekannte Markierungssequenz wurde gefunden", /* JBG_EMARKER */ + "Neue Daten passen nicht zu vorangegangenen Daten", /* JBG_ENOCONT */ + "Es wurden ung\303\274ltige Daten gefunden", /* JBG_EINVAL */ + "Noch nicht implementierte Optionen wurden benutzt" /* JBG_EIMPL */ + } +}; + + + +/* + * The following three functions are the only places in this code, were + * C library memory management functions are called. The whole JBIG + * library has been designed in order to allow multi-threaded + * execution. no static or global variables are used, so all fuctions + * are fully reentrant. However if you want to use this multi-thread + * capability and your malloc, realloc and free are not reentrant, + * then simply add the necessary semaphores or mutex primitives below. + */ + +static void *checked_malloc(size_t size) +{ + void *p; + + p = malloc(size); + /* Full manual exception handling is ugly here for performance + * reasons. If an adequate handling of lack of memory is required, + * then use C++ and throw a C++ exception here. */ + if (!p) + abort(); + +#if 0 + fprintf(stderr, "%p = malloc(%ld)\n", p, (long) size); +#endif + + return p; +} + + +static void *checked_realloc(void *ptr, size_t size) +{ + void *p; + + p = realloc(ptr, size); + /* Full manual exception handling is ugly here for performance + * reasons. If an adequate handling of lack of memory is required, + * then use C++ and throw a C++ exception here. */ + if (!p) + abort(); + +#if 0 + fprintf(stderr, "%p = realloc(%p, %ld)\n", p, ptr, (long) size); +#endif + + return p; +} + + +static void checked_free(void *ptr) +{ + free(ptr); + +#if 0 + fprintf(stderr, "free(%p)\n", ptr); +#endif + +} + + + +/* + * The next functions implement the arithmedic encoder and decoder + * required for JBIG. The same algorithm is also used in the arithmetic + * variant of JPEG. + */ + +#ifdef DEBUG +static long encoded_pixels = 0; +#endif + +ARITH void arith_encode_init(struct jbg_arenc_state *s, int reuse_st) +{ + int i; + + if (!reuse_st) + for (i = 0; i < 4096; s->st[i++] = 0); + s->c = 0; + s->a = 0x10000L; + s->sc = 0; + s->ct = 11; + s->buffer = -1; /* empty */ + + return; +} + + +ARITH void arith_encode_flush(struct jbg_arenc_state *s) +{ + unsigned long temp; + +#ifdef DEBUG + fprintf(stderr, " encoded pixels = %ld, a = %05lx, c = %08lx\n", + encoded_pixels, s->a, s->c); +#endif + + /* find the s->c in the coding interval with the largest + * number of trailing zero bits */ + if ((temp = (s->a - 1 + s->c) & 0xffff0000L) < s->c) + s->c = temp + 0x8000; + else + s->c = temp; + /* send remaining bytes to output */ + s->c <<= s->ct; + if (s->c & 0xf8000000L) { + /* one final overflow has to be handled */ + if (s->buffer >= 0) { + s->byte_out(s->buffer + 1, s->file); + if (s->buffer + 1 == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + } + /* output 0x00 bytes only when more non-0x00 will follow */ + if (s->c & 0x7fff800L) + for (; s->sc; --s->sc) + s->byte_out(0x00, s->file); + } else { + if (s->buffer >= 0) + s->byte_out(s->buffer, s->file); + /* T.82 figure 30 says buffer+1 for the above line! Typo? */ + for (; s->sc; --s->sc) { + s->byte_out(0xff, s->file); + s->byte_out(MARKER_STUFF, s->file); + } + } + /* output final bytes only if they are not 0x00 */ + if (s->c & 0x7fff800L) { + s->byte_out((s->c >> 19) & 0xff, s->file); + if (((s->c >> 19) & 0xff) == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + if (s->c & 0x7f800L) { + s->byte_out((s->c >> 11) & 0xff, s->file); + if (((s->c >> 11) & 0xff) == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + } + } + + return; +} + + +ARITH_INL void arith_encode(struct jbg_arenc_state *s, int cx, int pix) +{ + extern short jbg_lsz[]; + extern unsigned char jbg_nmps[], jbg_nlps[]; + register unsigned lsz, ss; + register unsigned char *st; + long temp; + +#ifdef DEBUG + ++encoded_pixels; +#endif + + assert(cx >= 0 && cx < 4096); + st = s->st + cx; + ss = *st & 0x7f; + assert(ss < 113); + lsz = jbg_lsz[ss]; + +#if 0 + fprintf(stderr, "pix = %d, cx = %d, mps = %d, st = %3d, lsz = 0x%04x, " + "a = 0x%05lx, c = 0x%08lx, ct = %2d, buf = 0x%02x\n", + pix, cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct, + s->buffer); +#endif + + if (((pix << 7) ^ s->st[cx]) & 0x80) { + /* encode the less probable symbol */ + if ((s->a -= lsz) >= lsz) { + /* If the interval size (lsz) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency, otherwise code the LPS + * as usual: */ + s->c += s->a; + s->a = lsz; + } + /* Check whether MPS/LPS exchange is necessary + * and chose next probability estimator status */ + *st &= 0x80; + *st ^= jbg_nlps[ss]; + } else { + /* encode the more probable symbol */ + if ((s->a -= lsz) & 0xffff8000L) + return; /* A >= 0x8000 -> ready, no renormalization required */ + if (s->a < lsz) { + /* If the interval size (lsz) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency: */ + s->c += s->a; + s->a = lsz; + } + /* chose next probability estimator status */ + *st &= 0x80; + *st |= jbg_nmps[ss]; + } + + /* renormalization of coding interval */ + do { + s->a <<= 1; + s->c <<= 1; + --s->ct; + if (s->ct == 0) { + /* another byte is ready for output */ + temp = s->c >> 19; + if (temp & 0xffffff00L) { + /* handle overflow over all buffered 0xff bytes */ + if (s->buffer >= 0) { + ++s->buffer; + s->byte_out(s->buffer, s->file); + if (s->buffer == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + } + for (; s->sc; --s->sc) + s->byte_out(0x00, s->file); + s->buffer = temp & 0xff; /* new output byte, might overflow later */ + assert(s->buffer != 0xff); + /* can s->buffer really never become 0xff here? */ + } else if (temp == 0xff) { + /* buffer 0xff byte (which might overflow later) */ + ++s->sc; + } else { + /* output all buffered 0xff bytes, they will not overflow any more */ + if (s->buffer >= 0) + s->byte_out(s->buffer, s->file); + for (; s->sc; --s->sc) { + s->byte_out(0xff, s->file); + s->byte_out(MARKER_STUFF, s->file); + } + s->buffer = temp; /* buffer new output byte (can still overflow) */ + } + s->c &= 0x7ffffL; + s->ct = 8; + } + } while (s->a < 0x8000); + + return; +} + + +ARITH void arith_decode_init(struct jbg_ardec_state *s, int reuse_st) +{ + int i; + + if (!reuse_st) + for (i = 0; i < 4096; s->st[i++] = 0); + s->c = 0; + s->a = 1; + s->ct = 0; + s->result = JBG_OK; + s->startup = 1; + return; +} + + +ARITH_INL int arith_decode(struct jbg_ardec_state *s, int cx) +{ + extern short jbg_lsz[]; + extern unsigned char jbg_nmps[], jbg_nlps[]; + register unsigned lsz, ss; + register unsigned char *st; + int pix; + + /* renormalization */ + while (s->a < 0x8000 || s->startup) { + if (s->ct < 1 && s->result != JBG_READY) { + /* first we have to move a new byte into s->c */ + if (s->pscd_ptr >= s->pscd_end) { + s->result = JBG_MORE; + return -1; + } + if (*s->pscd_ptr == 0xff) + if (s->pscd_ptr + 1 >= s->pscd_end) { + s->result = JBG_MARKER; + return -1; + } else { + if (*(s->pscd_ptr + 1) == MARKER_STUFF) { + s->c |= 0xffL << (8 - s->ct); + s->ct += 8; + s->pscd_ptr += 2; + s->result = JBG_OK; + } else + s->result = JBG_READY; + } + else { + s->c |= (long)*(s->pscd_ptr++) << (8 - s->ct); + s->ct += 8; + s->result = JBG_OK; + } + } + s->c <<= 1; + s->a <<= 1; + --s->ct; + if (s->a == 0x10000L) + s->startup = 0; + } + + st = s->st + cx; + ss = *st & 0x7f; + assert(ss < 113); + lsz = jbg_lsz[ss]; + +#if 0 + fprintf(stderr, "cx = %d, mps = %d, st = %3d, lsz = 0x%04x, a = 0x%05lx, " + "c = 0x%08lx, ct = %2d\n", + cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct); +#endif + + if ((s->c >> 16) < (s->a -= lsz)) + if (s->a & 0xffff8000L) + return *st >> 7; + else { + /* MPS_EXCHANGE */ + if (s->a < lsz) { + pix = 1 - (*st >> 7); + /* Check whether MPS/LPS exchange is necessary + * and chose next probability estimator status */ + *st &= 0x80; + *st ^= jbg_nlps[ss]; + } else { + pix = *st >> 7; + *st &= 0x80; + *st |= jbg_nmps[ss]; + } + } + else { + /* LPS_EXCHANGE */ + if (s->a < lsz) { + s->c -= s->a << 16; + s->a = lsz; + pix = *st >> 7; + *st &= 0x80; + *st |= jbg_nmps[ss]; + } else { + s->c -= s->a << 16; + s->a = lsz; + pix = 1 - (*st >> 7); + /* Check whether MPS/LPS exchange is necessary + * and chose next probability estimator status */ + *st &= 0x80; + *st ^= jbg_nlps[ss]; + } + } + + return pix; +} + + + +/* + * Memory management for buffers which are used for temporarily + * storing SDEs by the encoder. + * + * The following functions manage a set of struct jbg_buf storage + * containers were each can keep JBG_BUFSIZE bytes. The jbg_buf + * containers can be linked to form linear double-chained lists for + * which a number of operations are provided. Blocks which are + * tempoarily not used any more are returned to a freelist which each + * encoder keeps. Only the destructor of the encoder actually returns + * the block via checked_free() to the stdlib memory management. + */ + + +/* + * Allocate a new buffer block and initialize it. Try to get it from + * the free_list, and if it is empty, call checked_malloc(). + */ +static struct jbg_buf *jbg_buf_init(struct jbg_buf **free_list) +{ + struct jbg_buf *new_block; + + /* Test whether a block from the free list is available */ + if (*free_list) { + new_block = *free_list; + *free_list = new_block->next; + } else { + /* request a new memory block */ + new_block = (struct jbg_buf *) checked_malloc(sizeof(struct jbg_buf)); + } + new_block->len = 0; + new_block->next = NULL; + new_block->previous = NULL; + new_block->last = new_block; + new_block->free_list = free_list; + + return new_block; +} + + +/* + * Return an entire free_list to the memory management of stdlib. + * This is only done by jbg_enc_free(). + */ +static void jbg_buf_free(struct jbg_buf **free_list) +{ + struct jbg_buf *tmp; + + while (*free_list) { + tmp = (*free_list)->next; + checked_free(*free_list); + *free_list = tmp; + } + + return; +} + + +/* + * Append a single byte to a single list that starts with the block + * *(struct jbg_buf *) head. The type of *head is void here in order to + * keep the interface of the arithmetic encoder gereric, which uses this + * function as a call-back function in order to deliver single bytes + * for a PSCD. + */ +static void jbg_buf_write(int b, void *head) +{ + struct jbg_buf *now; + + now = ((struct jbg_buf *) head)->last; + if (now->len < JBG_BUFSIZE - 1) { + now->d[now->len++] = b; + return; + } + now->next = jbg_buf_init(((struct jbg_buf *) head)->free_list); + now->next->previous = now; + now->next->d[now->next->len++] = b; + ((struct jbg_buf *) head)->last = now->next; + + return; +} + + +/* + * Remove any trailing zero bytes from the end of a linked jbg_buf list, + * however make sure that no zero byte is removed which directly + * follows a 0xff byte (i.e., keep MARKER_ESC MARKER_STUFF sequences + * intact). This function is used to remove any redundant final zero + * bytes from a PSCD. + */ +static void jbg_buf_remove_zeros(struct jbg_buf *head) +{ + struct jbg_buf *last; + + while (1) { + /* remove trailing 0x00 in last block of list until this block is empty */ + last = head->last; + while (last->len && last->d[last->len - 1] == 0) + last->len--; + /* if block became really empty, remove it in case it is not the + * only remaining block and then loop to next block */ + if (last->previous && !last->len) { + head->last->next = *head->free_list; + *head->free_list = head->last; + head->last = last->previous; + head->last->next = NULL; + } else + break; + } + + /* + * If the final non-zero byte is 0xff (MARKER_ESC), then we just have + * removed a MARKER_STUFF and we will append it again now in order + * to preserve PSCD status of byte stream. + */ + if (head->last->len && head->last->d[head->last->len - 1] == MARKER_ESC) + jbg_buf_write(MARKER_STUFF, head); + + return; +} + + +/* + * The jbg_buf list which starts with block *new_prefix is concatenated + * with the list which starts with block **start and *start will then point + * to the first block of the new list. + */ +static void jbg_buf_prefix(struct jbg_buf *new_prefix, struct jbg_buf **start) +{ + new_prefix->last->next = *start; + new_prefix->last->next->previous = new_prefix->last; + new_prefix->last = new_prefix->last->next->last; + *start = new_prefix; + + return; +} + + +/* + * Send the contents of a jbg_buf list that starts with block **head to + * the call back function data_out and return the blocks of the jbg_buf + * list to the freelist from which these jbg_buf blocks have been taken. + * After the call, *head == NULL. + */ +static void jbg_buf_output(struct jbg_buf **head, + void (*data_out)(unsigned char *start, + size_t len, void *file), + void *file) +{ + struct jbg_buf *tmp; + + while (*head) { + data_out((*head)->d, (*head)->len, file); + tmp = (*head)->next; + (*head)->next = *(*head)->free_list; + *(*head)->free_list = *head; + *head = tmp; + } + + return; +} + + +/* + * Calculate y = ceil(x/2) applied n times. This function is used to + * determine the number of pixels per row or column after n resolution + * reductions. E.g. X[d-1] = jbg_ceil_half(X[d], 1) and X[0] = + * jbg_ceil_half(X[d], d) as defined in clause 6.2.3 of T.82. + */ +unsigned long jbg_ceil_half(unsigned long x, int n) +{ + unsigned long mask; + + mask = (1UL << n) - 1; /* the lowest n bits are 1 here */ + return (x >> n) + ((mask & x) != 0); +} + + +/* + * Initialize the status struct for the encoder. + */ +void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, + int planes, unsigned char **p, + void (*data_out)(unsigned char *start, size_t len, + void *file), + void *file) +{ + unsigned long l, lx; + int i; + size_t bufsize; + + extern char jbg_resred[], jbg_dptable[]; + + s->xd = x; + s->yd = y; + s->planes = planes; + s->data_out = data_out; + s->file = file; + + s->d = 0; + s->dl = 0; + s->dh = s->d; + s->l0 = jbg_ceil_half(s->yd, s->d) / 35; /* 35 stripes/image */ + while ((s->l0 << s->d) > 128) /* but <= 128 lines/stripe */ + --s->l0; + if (s->l0 < 2) s->l0 = 2; + s->mx = 8; + s->my = 0; + s->order = JBG_ILEAVE | JBG_SMID; + s->options = JBG_TPBON | JBG_TPDON | JBG_DPON; + s->dppriv = jbg_dptable; + s->res_tab = jbg_resred; + + s->highres = checked_malloc(planes * sizeof(int)); + s->lhp[0] = p; + s->lhp[1] = checked_malloc(planes * sizeof(unsigned char *)); + bufsize = ((jbg_ceil_half(x, 1) + 7) / 8) * jbg_ceil_half(y, 1); + for (i = 0; i < planes; i++) { + s->highres[i] = 0; + s->lhp[1][i] = checked_malloc(sizeof(unsigned char) * bufsize); + } + + s->free_list = NULL; + s->s = (struct jbg_arenc_state *) + checked_malloc(s->planes * sizeof(struct jbg_arenc_state)); + s->tx = (int *) checked_malloc(s->planes * sizeof(int)); + lx = jbg_ceil_half(x, 1); + s->tp = (char *) checked_malloc(lx * sizeof(char)); + for (l = 0; l < lx; s->tp[l++] = 2); + s->sde = NULL; + + return; +} + + +/* + * This function selects the number of differential layers based on + * the maximum size requested for the lowest resolution layer. If + * possible, a number of differential layers is selected, which will + * keep the size of the lowest resolution layer below or equal to the + * given width x and height y. However not more than 6 differential + * resolution layers will be used. In addition, a reasonable value for + * l0 (height of one stripe in the lowest resolution layer) is + * selected, which obeys the recommended limitations for l0 in annex A + * and C of the JBIG standard. The selected number of resolution layers + * is returned. + */ +int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, + unsigned long y) +{ + for (s->d = 0; s->d < 6; s->d++) + if (jbg_ceil_half(s->xd, s->d) <= x && jbg_ceil_half(s->yd, s->d) <= y) + break; + s->dl = 0; + s->dh = s->d; + + s->l0 = jbg_ceil_half(s->yd, s->d) / 35; /* 35 stripes/image */ + while ((s->l0 << s->d) > 128) /* but <= 128 lines/stripe */ + --s->l0; + if (s->l0 < 2) s->l0 = 2; + + return s->d; +} + + +/* + * As an alternative to jbg_enc_lrlmax(), the following function allows + * to specify the number of layers directly. The stripe height and layer + * range is also adjusted automatically here. + */ +void jbg_enc_layers(struct jbg_enc_state *s, int d) +{ + if (d < 0 || d > 255) + return; + s->d = d; + s->dl = 0; + s->dh = s->d; + + s->l0 = jbg_ceil_half(s->yd, s->d) / 35; /* 35 stripes/image */ + while ((s->l0 << s->d) > 128) /* but <= 128 lines/stripe */ + --s->l0; + if (s->l0 < 2) s->l0 = 2; + + return; +} + + +/* + * Specify the highest and lowest resolution layers which will be + * written to the output file. Call this function not before + * jbg_enc_layers() or jbg_enc_lrlmax(), because these two functions + * reset the lowest and highest resolution layer to default values. + * Negative values are ignored. The total number of layers is returned. + */ +int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh) +{ + if (dl >= 0 && dl <= s->d) s->dl = dl; + if (dh >= s->dl && dh <= s->d) s->dh = dh; + + return s->d; +} + + +/* + * The following function allows to specify the bits describing the + * options of the format as well as the maximum AT movement window and + * the number of layer 0 lines per stripes. + */ +void jbg_enc_options(struct jbg_enc_state *s, int order, int options, + long l0, int mx, int my) +{ + if (order >= 0 && order <= 0x0f) s->order = order; + if (options >= 0) s->options = options; + if (l0 >= 0) s->l0 = l0; + if (mx >= 0 && my < 128) s->mx = mx; + if (my >= 0 && my < 256) s->my = my; + + return; +} + + +/* + * This function actually does all the tricky work involved in producing + * a SDE, which is stored in the appropriate s->sde[][][] element + * for later output in the correct order. + */ +static void encode_sde(struct jbg_enc_state *s, + long stripe, int layer, int plane) +{ + unsigned char *hp, *lp1, *lp2, *p0, *p1, *q1, *q2; + unsigned long hl, ll, hx, hy, lx, ly, hbpl, lbpl; + unsigned long line_h0 = 0, line_h1 = 0; + unsigned long line_h2, line_h3, line_l1, line_l2, line_l3; + struct jbg_arenc_state *se; + unsigned long i, j, y; + unsigned t; + int ltp, ltp_old, cx; + unsigned long c_all, c[MX_MAX + 1], cmin, cmax, clmin, clmax; + int tmax, at_determined; + int new_tx; + long new_tx_line = -1; + struct jbg_buf *new_jbg_buf; + +#ifdef DEBUG + static long tp_lines, tp_exceptions, tp_pixels, dp_pixels; + static long encoded_pixels; +#endif + + /* return immediately if this stripe has already been encoded */ + if (s->sde[stripe][layer][plane] != SDE_TODO) + return; + +#ifdef DEBUG + if (stripe == 0) + tp_lines = tp_exceptions = tp_pixels = dp_pixels = encoded_pixels = 0; + fprintf(stderr, "encode_sde: s/d/p = %2ld/%2d/%2d\n", + stripe, layer, plane); +#endif + + /* number of lines per stripe in highres image */ + hl = s->l0 << layer; + /* number of lines per stripe in lowres image */ + ll = hl >> 1; + /* current line number in highres image */ + y = stripe * hl; + /* number of pixels in highres image */ + hx = jbg_ceil_half(s->xd, s->d - layer); + hy = jbg_ceil_half(s->yd, s->d - layer); + /* number of pixels in lowres image */ + lx = jbg_ceil_half(hx, 1); + ly = jbg_ceil_half(hy, 1); + /* bytes per line in highres and lowres image */ + hbpl = (hx + 7) / 8; + lbpl = (lx + 7) / 8; + /* pointer to first image byte of highres stripe */ + hp = s->lhp[s->highres[plane]][plane] + stripe * hl * hbpl; + lp2 = s->lhp[1 - s->highres[plane]][plane] + stripe * ll * lbpl; + lp1 = lp2 + lbpl; + + /* initialize arithmetic encoder */ + se = s->s + plane; + arith_encode_init(se, stripe != 0); + s->sde[stripe][layer][plane] = jbg_buf_init(&s->free_list); + se->byte_out = jbg_buf_write; + se->file = s->sde[stripe][layer][plane]; + + /* initialize adaptive template movement algorithm */ + c_all = 0; + for (t = 0; t <= s->mx; t++) + c[t] = 0; + if (stripe == 0) + s->tx[plane] = 0; + new_tx = -1; + at_determined = 0; /* we haven't yet decided the template move */ + if (s->mx == 0) + at_determined = 1; + + /* initialize typical prediction */ + ltp = 0; + if (stripe == 0) + ltp_old = 0; + else { + ltp_old = 1; + p1 = hp - hbpl; + if (y > 1) { + q1 = p1 - hbpl; + while (p1 < hp && (ltp_old = (*p1++ == *q1++)) != 0); + } else + while (p1 < hp && (ltp_old = (*p1++ == 0)) != 0); + } + + if (layer == 0) { + + /* + * Encode lowest resolution layer + */ + + for (i = 0; i < hl && y < hy; i++, y++) { + + /* check whether it is worth to perform an ATMOVE */ + if (!at_determined && c_all > 2048) { + cmin = clmin = 0xffffffffL; + cmax = clmax = 0; + tmax = 0; + for (t = (s->options & JBG_LRLTWO) ? 5 : 3; t <= s->mx; t++) { + if (c[t] > cmax) cmax = c[t]; + if (c[t] < cmin) cmin = c[t]; + if (c[t] > c[tmax]) tmax = t; + } + clmin = (c[0] < cmin) ? c[0] : cmin; + clmax = (c[0] > cmax) ? c[0] : cmax; + if (c_all - cmax < (c_all >> 3) && + cmax - c[s->tx[plane]] > c_all - cmax && + cmax - c[s->tx[plane]] > (c_all >> 4) && + /* ^ T.82 says here < !!! Typo ? */ + cmax - (c_all - c[s->tx[plane]]) > c_all - cmax && + cmax - (c_all - c[s->tx[plane]]) > (c_all >> 4) && + cmax - cmin > (c_all >> 2) && + (s->tx[plane] || clmax - clmin > (c_all >> 3))) { + /* we have decided to perform an ATMOVE */ + new_tx = tmax; + if (!(s->options & JBG_DELAY_AT)) { + new_tx_line = i; + s->tx[plane] = new_tx; + } + } + at_determined = 1; + } + + /* typical prediction */ + if (s->options & JBG_TPBON) { + ltp = 1; + p1 = hp; + if (y > 0) { + q1 = hp - hbpl; + while (q1 < hp && (ltp = (*p1++ == *q1++)) != 0); + } else + while (p1 < hp + hbpl && (ltp = (*p1++ == 0)) != 0); + arith_encode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX, + ltp == ltp_old); +#ifdef DEBUG + tp_lines += ltp; +#endif + ltp_old = ltp; + if (ltp) { + /* skip next line */ + hp += hbpl; + continue; + } + } + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the neighbour pixels of the currently coded pixel X: + * + * 76543210765432107654321076543210 line_h3 + * 76543210765432107654321076543210 line_h2 + * 76543210765432107654321X76543210 line_h1 + */ + + line_h1 = line_h2 = line_h3 = 0; + if (y > 0) line_h2 = (long)*(hp - hbpl) << 8; + if (y > 1) line_h3 = (long)*(hp - hbpl - hbpl) << 8; + + /* encode line */ + for (j = 0; j < hx; hp++) { + line_h1 |= *hp; + if (j < hbpl * 8 - 8 && y > 0) { + line_h2 |= *(hp - hbpl + 1); + if (y > 1) + line_h3 |= *(hp - hbpl - hbpl + 1); + } + if (s->options & JBG_LRLTWO) { + /* two line template */ + do { + line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; + if (s->tx[plane]) + arith_encode(se, (((line_h2 >> 10) & 0x3e0) | + ((line_h1 >> (4 + s->tx[plane])) & 0x010) | + ((line_h1 >> 9) & 0x00f)), + (line_h1 >> 8) & 1); + else + arith_encode(se, (((line_h2 >> 10) & 0x3f0) | + ((line_h1 >> 9) & 0x00f)), + (line_h1 >> 8) & 1); +#ifdef DEBUG + encoded_pixels++; +#endif + /* statistics for adaptive template changes */ + if (!at_determined && j >= s->mx && j < hx-2) { + c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100); + for (t = 5; t <= s->mx; t++) + c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100); + ++c_all; + } + } while (++j & 7 && j < hx); + } else { + /* three line template */ + do { + line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; + if (s->tx[plane]) + arith_encode(se, (((line_h3 >> 8) & 0x380) | + ((line_h2 >> 12) & 0x078) | + ((line_h1 >> (6 + s->tx[plane])) & 0x004) | + ((line_h1 >> 9) & 0x003)), + (line_h1 >> 8) & 1); + else + arith_encode(se, (((line_h3 >> 8) & 0x380) | + ((line_h2 >> 12) & 0x07c) | + ((line_h1 >> 9) & 0x003)), + (line_h1 >> 8) & 1); +#ifdef DEBUG + encoded_pixels++; +#endif + /* statistics for adaptive template changes */ + if (!at_determined && j >= s->mx && j < hx-2) { + c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100); + for (t = 3; t <= s->mx; t++) + c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100); + ++c_all; + } + } while (++j & 7 && j < hx); + } /* if (s->options & JBG_LRLTWO) */ + } /* for (j = ...) */ + } /* for (i = ...) */ + + } else { + + /* + * Encode differential layer + */ + + for (i = 0; i < hl && y < hy; i++, y++) { + + /* check whether it is worth to perform an ATMOVE */ + if (!at_determined && c_all > 2048) { + cmin = clmin = 0xffffffffL; + cmax = clmax = 0; + tmax = 0; + for (t = 3; t <= s->mx; t++) { + if (c[t] > cmax) cmax = c[t]; + if (c[t] < cmin) cmin = c[t]; + if (c[t] > c[tmax]) tmax = t; + } + clmin = (c[0] < cmin) ? c[0] : cmin; + clmax = (c[0] > cmax) ? c[0] : cmax; + if (c_all - cmax < (c_all >> 3) && + cmax - c[s->tx[plane]] > c_all - cmax && + cmax - c[s->tx[plane]] > (c_all >> 4) && + /* ^ T.82 says here < !!! Typo ? */ + cmax - (c_all - c[s->tx[plane]]) > c_all - cmax && + cmax - (c_all - c[s->tx[plane]]) > (c_all >> 4) && + cmax - cmin > (c_all >> 2) && + (s->tx[plane] || clmax - clmin > (c_all >> 3))) { + /* we have decided to perform an ATMOVE */ + new_tx = tmax; + if (!(s->options & JBG_DELAY_AT)) { + new_tx_line = i; + s->tx[plane] = new_tx; + } +#ifdef DEBUG + fprintf(stderr, "ATMOVE: line=%ld, tx=%d, c_all=%ld\n", + i, new_tx, c_all); +#endif + } + at_determined = 1; + } + + if ((i >> 1) >= ll - 1 || (y >> 1) >= ly - 1) + lp1 = lp2; + + /* typical prediction */ + if (s->options & JBG_TPDON && (i & 1) == 0) { + q1 = lp1; q2 = lp2; + p0 = p1 = hp; + if (i < hl - 1 && y < hy - 1) + p0 = hp + hbpl; + if (y > 1) + line_l3 = (long)*(q2 - lbpl) << 8; + else + line_l3 = 0; + line_l2 = (long)*q2 << 8; + line_l1 = (long)*q1 << 8; + ltp = 1; + for (j = 0; j < lx && ltp; q1++, q2++) { + if (j < lbpl * 8 - 8) { + if (y > 1) + line_l3 |= *(q2 - lbpl + 1); + line_l2 |= *(q2 + 1); + line_l1 |= *(q1 + 1); + } + do { + if ((j >> 2) < hbpl) { + line_h1 = *(p1++); + line_h0 = *(p0++); + } + do { + line_l3 <<= 1; + line_l2 <<= 1; + line_l1 <<= 1; + line_h1 <<= 2; + line_h0 <<= 2; + cx = (((line_l3 >> 15) & 0x007) | + ((line_l2 >> 12) & 0x038) | + ((line_l1 >> 9) & 0x1c0)); + if (cx == 0x000) + if ((line_h1 & 0x300) == 0 && (line_h0 & 0x300) == 0) + s->tp[j] = 0; + else { + ltp = 0; +#ifdef DEBUG + tp_exceptions++; +#endif + } + else if (cx == 0x1ff) + if ((line_h1 & 0x300) == 0x300 && (line_h0 & 0x300) == 0x300) + s->tp[j] = 1; + else { + ltp = 0; +#ifdef DEBUG + tp_exceptions++; +#endif + } + else + s->tp[j] = 2; + } while (++j & 3 && j < lx); + } while (j & 7 && j < lx); + } /* for (j = ...) */ + arith_encode(se, TPDCX, !ltp); +#ifdef DEBUG + tp_lines += ltp; +#endif + } + + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the high resolution neighbour pixels of the currently coded + * highres pixel X: + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 76543210 76543210 line_h2 + * 76543210 76543210 7654321X 76543210 line_h1 + * + * Layout of the variables line_l1, line_l2, line_l3, which contain + * the low resolution pixels near the currently coded pixel as bits. + * The lowres pixel in which the currently coded highres pixel is + * located is marked as Y: + * + * 76543210 76543210 76543210 76543210 line_l3 + * 76543210 7654321Y 76543210 76543210 line_l2 + * 76543210 76543210 76543210 76543210 line_l1 + */ + + + line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0; + if (y > 0) line_h2 = (long)*(hp - hbpl) << 8; + if (y > 1) { + line_h3 = (long)*(hp - hbpl - hbpl) << 8; + line_l3 = (long)*(lp2 - lbpl) << 8; + } + line_l2 = (long)*lp2 << 8; + line_l1 = (long)*lp1 << 8; + + /* encode line */ + for (j = 0; j < hx; lp1++, lp2++) { + if ((j >> 1) < lbpl * 8 - 8) { + if (y > 1) + line_l3 |= *(lp2 - lbpl + 1); + line_l2 |= *(lp2 + 1); + line_l1 |= *(lp1 + 1); + } + do { + + assert(hp - (s->lhp[s->highres[plane]][plane] + + (stripe * hl + i) * hbpl) + == (ptrdiff_t) j >> 3); + + assert(lp2 - (s->lhp[1-s->highres[plane]][plane] + + (stripe * ll + (i>>1)) * lbpl) + == (ptrdiff_t) j >> 4); + + line_h1 |= *(hp++); + if (j < hbpl * 8 - 8) { + if (y > 0) { + line_h2 |= *(hp - hbpl); + if (y > 1) + line_h3 |= *(hp - hbpl - hbpl); + } + } + do { + line_l1 <<= 1; line_l2 <<= 1; line_l3 <<= 1; + if (ltp && s->tp[j >> 1] < 2) { + /* pixel are typical and have not to be encoded */ + line_h1 <<= 2; line_h2 <<= 2; line_h3 <<= 2; +#ifdef DEBUG + do { + ++tp_pixels; + } while (++j & 1 && j < hx); +#else + j += 2; +#endif + } else + do { + line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; + + /* deterministic prediction */ + if (s->options & JBG_DPON) { + if ((y & 1) == 0) { + if ((j & 1) == 0) { + /* phase 0 */ + if (s->dppriv[((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x010) | + ((line_h2 >> 10) & 0x0e0)] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } else { + /* phase 1 */ + if (s->dppriv[(((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x030) | + ((line_h2 >> 10) & 0x1c0)) + 256] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } + } else { + if ((j & 1) == 0) { + /* phase 2 */ + if (s->dppriv[(((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x010) | + ((line_h2 >> 10) & 0x0e0) | + ((line_h3 >> 7) & 0x700)) + 768] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } else { + /* phase 3 */ + if (s->dppriv[(((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x030) | + ((line_h2 >> 10) & 0x1c0) | + ((line_h3 >> 7) & 0xe00)) + 2816] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } + } + } + + /* determine context */ + if (s->tx[plane]) + cx = (((line_h1 >> 9) & 0x003) | + ((line_h1 >> (4 + s->tx[plane])) & 0x010) | + ((line_h2 >> 13) & 0x00c) | + ((line_h3 >> 11) & 0x020)); + else + cx = (((line_h1 >> 9) & 0x003) | + ((line_h2 >> 13) & 0x01c) | + ((line_h3 >> 11) & 0x020)); + if (j & 1) + cx |= (((line_l2 >> 9) & 0x0c0) | + ((line_l1 >> 7) & 0x300)) | (1UL << 10); + else + cx |= (((line_l2 >> 10) & 0x0c0) | + ((line_l1 >> 8) & 0x300)); + cx |= (y & 1) << 11; + + arith_encode(se, cx, (line_h1 >> 8) & 1); +#ifdef DEBUG + encoded_pixels++; +#endif + + /* statistics for adaptive template changes */ + if (!at_determined && j >= s->mx) { + c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100); + for (t = 3; t <= s->mx; t++) + c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100); + ++c_all; + } + + } while (++j & 1 && j < hx); + } while (j & 7 && j < hx); + } while (j & 15 && j < hx); + } /* for (j = ...) */ + + /* low resolution pixels are used twice */ + if ((i & 1) == 0) { + lp1 -= lbpl; + lp2 -= lbpl; + } + + } /* for (i = ...) */ + } + + arith_encode_flush(se); + jbg_buf_remove_zeros(s->sde[stripe][layer][plane]); + jbg_buf_write(MARKER_ESC, s->sde[stripe][layer][plane]); + jbg_buf_write(MARKER_SDNORM, s->sde[stripe][layer][plane]); + + /* add ATMOVE */ + if (new_tx != -1) { + if (s->options & JBG_DELAY_AT) { + /* ATMOVE will become active at the first line of the next stripe */ + s->tx[plane] = new_tx; + jbg_buf_write(MARKER_ESC, s->sde[stripe][layer][plane]); + jbg_buf_write(MARKER_ATMOVE, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(s->tx[plane], s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + } else { + /* ATMOVE has already become active during this stripe + * => we have to prefix the SDE data with an ATMOVE marker */ + new_jbg_buf = jbg_buf_init(&s->free_list); + jbg_buf_write(MARKER_ESC, new_jbg_buf); + jbg_buf_write(MARKER_ATMOVE, new_jbg_buf); + jbg_buf_write((new_tx_line >> 24) & 0xff, new_jbg_buf); + jbg_buf_write((new_tx_line >> 16) & 0xff, new_jbg_buf); + jbg_buf_write((new_tx_line >> 8) & 0xff, new_jbg_buf); + jbg_buf_write(new_tx_line & 0xff, new_jbg_buf); + jbg_buf_write(new_tx, new_jbg_buf); + jbg_buf_write(0, new_jbg_buf); + jbg_buf_prefix(new_jbg_buf, &s->sde[stripe][layer][plane]); + } + } + +#if 0 + if (stripe == s->stripes - 1) + fprintf(stderr, "tp_lines = %ld, tp_exceptions = %ld, tp_pixels = %ld, " + "dp_pixels = %ld, encoded_pixels = %ld\n", + tp_lines, tp_exceptions, tp_pixels, dp_pixels, encoded_pixels); +#endif + + return; +} + + +/* + * Create the next lower resolution version of an image + */ +static void resolution_reduction(struct jbg_enc_state *s, int plane, + int higher_layer) +{ + unsigned long hx, hy, lx, ly, hbpl, lbpl; + unsigned char *hp1, *hp2, *hp3, *lp; + unsigned long line_h1, line_h2, line_h3, line_l2; + unsigned long i, j; + int pix, k, l; + + /* number of pixels in highres image */ + hx = jbg_ceil_half(s->xd, s->d - higher_layer); + hy = jbg_ceil_half(s->yd, s->d - higher_layer); + /* number of pixels in lowres image */ + lx = jbg_ceil_half(hx, 1); + ly = jbg_ceil_half(hy, 1); + /* bytes per line in highres and lowres image */ + hbpl = (hx + 7) / 8; + lbpl = (lx + 7) / 8; + /* pointers to first image bytes */ + hp2 = s->lhp[s->highres[plane]][plane]; + hp1 = hp2 + hbpl; + hp3 = hp2 - hbpl; + lp = s->lhp[1 - s->highres[plane]][plane]; + +#ifdef DEBUG + fprintf(stderr, "resolution_reduction: plane = %d, higher_layer = %d\n", + plane, higher_layer); +#endif + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the high resolution neighbour pixels of the currently coded + * lowres pixel /\: + * \/ + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 765432/\ 76543210 line_h2 + * 76543210 76543210 765432\/ 76543210 line_h1 + * + * Layout of the variable line_l2, which contains the low resolution + * pixels near the currently coded pixel as bits. The lowres pixel + * which is currently coded is marked as X: + * + * 76543210 76543210 76543210 76543210 line_l2 + * X + */ + + for (i = 0; i < ly; i++) { + if (2*i + 1 >= hy) + hp1 = hp2; + pix = 0; + line_h1 = line_h2 = line_h3 = line_l2 = 0; + for (j = 0; j < lbpl * 8; j += 8) { + *lp = 0; + line_l2 |= i ? lp[-lbpl] : 0; + for (k = 0; k < 8 && j + k < lx; k += 4) { + if (((j + k) >> 2) < hbpl) { + line_h3 |= i ? *hp3 : 0; + ++hp3; + line_h2 |= *(hp2++); + line_h1 |= *(hp1++); + } + for (l = 0; l < 4 && j + k + l < lx; l++) { + line_h3 <<= 2; + line_h2 <<= 2; + line_h1 <<= 2; + line_l2 <<= 1; + pix = s->res_tab[((line_h1 >> 8) & 0x007) | + ((line_h2 >> 5) & 0x038) | + ((line_h3 >> 2) & 0x1c0) | + (pix << 9) | ((line_l2 << 2) & 0xc00)]; + *lp = (*lp << 1) | pix; + } + } + ++lp; + } + *(lp - 1) <<= lbpl * 8 - lx; + hp1 += hbpl; + hp2 += hbpl; + hp3 += hbpl; + } + +#ifdef DEBUG + { + FILE *f; + char fn[50]; + + sprintf(fn, "dbg_d=%02d.pbm", higher_layer - 1); + f = fopen(fn, "wb"); + fprintf(f, "P4\n%lu %lu\n", lx, ly); + fwrite(s->lhp[1 - s->highres[plane]][plane], 1, lbpl * ly, f); + fclose(f); + } +#endif + + return; +} + + +/* + * This function is called inside the three loops of jbg_enc_out() in + * order to write the next SDE. It has first to generate the required + * SDE and all SDEs which have to be encoded before this SDE can be + * created. The problem here is that if we want to output a lower + * resolution layer, we have to allpy the resolution reduction + * algorithm in order to get it. As we try to safe as much memory as + * possible, the resolution reduction will overwrite previous higher + * resolution bitmaps. Consequently, we have to encode and buffer SDEs + * which depend on higher resolution layers before we can start the + * resolution reduction. All this logic about which SDE has to be + * encoded before resolution reduction is allowed is handled here. + * This approach might be a little bit more complex than alternative + * ways to do it, but it allows us to do the encoding with the minimal + * possible amount of temporary memory. + */ +static void output_sde(struct jbg_enc_state *s, + unsigned long stripe, int layer, int plane) +{ + int lfcl; /* lowest fully coded layer */ + long i; + unsigned long u; + + assert(s->sde[stripe][layer][plane] != SDE_DONE); + + if (s->sde[stripe][layer][plane] != SDE_TODO) { +#ifdef DEBUG + fprintf(stderr, "writing SDE: s/d/p = %2lu/%2d/%2d\n", + stripe, layer, plane); +#endif + jbg_buf_output(&s->sde[stripe][layer][plane], s->data_out, s->file); + s->sde[stripe][layer][plane] = SDE_DONE; + return; + } + + /* Determine the smallest resolution layer in this plane for which + * not yet all stripes have been encoded into SDEs. This layer will + * have to be completely coded, before we can apply the next + * resolution reduction step. */ + lfcl = 0; + for (i = s->d; i >= 0; i--) + if (s->sde[s->stripes - 1][i][plane] == SDE_TODO) { + lfcl = i + 1; + break; + } + if (lfcl > s->d && s->d > 0 && stripe == 0) { + /* perform the first resolution reduction */ + resolution_reduction(s, plane, s->d); + } + /* In case HITOLO is not used, we have to encode and store the higher + * resolution layers first, although we do not need them right now. */ + while (lfcl - 1 > layer) { + for (u = 0; u < s->stripes; u++) + encode_sde(s, u, lfcl - 1, plane); + --lfcl; + s->highres[plane] ^= 1; + if (lfcl > 1) + resolution_reduction(s, plane, lfcl - 1); + } + + encode_sde(s, stripe, layer, plane); + +#ifdef DEBUG + fprintf(stderr, "writing SDE: s/d/p = %2lu/%2d/%2d\n", stripe, layer, plane); +#endif + jbg_buf_output(&s->sde[stripe][layer][plane], s->data_out, s->file); + s->sde[stripe][layer][plane] = SDE_DONE; + + if (stripe == s->stripes - 1 && layer > 0 && + s->sde[0][layer-1][plane] == SDE_TODO) { + s->highres[plane] ^= 1; + if (layer > 1) + resolution_reduction(s, plane, layer - 1); + } + + return; +} + + +/* + * Convert the table which controls the deterministic prediction + * process from the internal format into the representation required + * for the 1728 byte long DPTABLE element of a BIH. + * + * The bit order of the DPTABLE format (see also ITU-T T.82 figure 13) is + * + * high res: 4 5 6 low res: 0 1 + * 7 8 9 2 3 + * 10 11 12 + * + * were 4 table entries are packed into one byte, while we here use + * internally an unpacked 6912 byte long table indexed by the following + * bit order: + * + * high res: 7 6 5 high res: 8 7 6 low res: 1 0 + * (phase 0) 4 . . (phase 1) 5 4 . 3 2 + * . . . . . . + * + * high res: 10 9 8 high res: 11 10 9 + * (phase 2) 7 6 5 (phase 3) 8 7 6 + * 4 . . 5 4 . + */ +void jbg_int2dppriv(unsigned char *dptable, const char *internal) +{ + int i, j, k; + int trans0[ 8] = { 1, 0, 3, 2, 7, 6, 5, 4 }; + int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 }; + int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 }; + int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 }; + + for (i = 0; i < 1728; dptable[i++] = 0); + +#define FILL_TABLE1(offset, len, trans) \ + for (i = 0; i < len; i++) { \ + k = 0; \ + for (j = 0; j < 8; j++) \ + k |= ((i >> j) & 1) << trans[j]; \ + dptable[(i + offset) >> 2] |= \ + (internal[k + offset] & 3) << ((3 - (i&3)) << 1); \ + } + + FILL_TABLE1( 0, 256, trans0); + FILL_TABLE1( 256, 512, trans1); + FILL_TABLE1( 768, 2048, trans2); + FILL_TABLE1(2816, 4096, trans3); + + return; +} + + +/* + * Convert the table which controls the deterministic prediction + * process from the 1728 byte long DPTABLE format into the 6912 byte long + * internal format. + */ +void jbg_dppriv2int(char *internal, const unsigned char *dptable) +{ + int i, j, k; + int trans0[ 8] = { 1, 0, 3, 2, 7, 6, 5, 4 }; + int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 }; + int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 }; + int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 }; + +#define FILL_TABLE2(offset, len, trans) \ + for (i = 0; i < len; i++) { \ + k = 0; \ + for (j = 0; j < 8; j++) \ + k |= ((i >> j) & 1) << trans[j]; \ + internal[k + offset] = \ + (dptable[(i + offset) >> 2] >> ((3 - (i & 3)) << 1)) & 3; \ + } + + FILL_TABLE2( 0, 256, trans0); + FILL_TABLE2( 256, 512, trans1); + FILL_TABLE2( 768, 2048, trans2); + FILL_TABLE2(2816, 4096, trans3); + + return; +} + + +/* + * Encode one full BIE and pass the generated data to the specified + * call-back function + */ +void jbg_enc_out(struct jbg_enc_state *s) +{ + long bpl; + unsigned char bih[20]; + unsigned long xd, yd, y; + long ii[3], is[3], ie[3]; /* generic variables for the 3 nested loops */ + unsigned long stripe; + int layer, plane; + int order; + unsigned char dpbuf[1728]; + extern char jbg_dptable[]; + + /* some sanity checks */ + s->order &= JBG_HITOLO | JBG_SEQ | JBG_ILEAVE | JBG_SMID; + order = s->order & (JBG_SEQ | JBG_ILEAVE | JBG_SMID); + if (index[order][0] < 0) + s->order = order = JBG_SMID | JBG_ILEAVE; + if (s->options & JBG_DPON && s->dppriv != jbg_dptable) + s->options |= JBG_DPPRIV; + if (s->mx > MX_MAX) + s->mx = MX_MAX; + s->my = 0; + if (s->mx && s->mx < ((s->options & JBG_LRLTWO) ? 5U : 3U)) + s->mx = 0; + if (s->d > 255 || s->d < 0 || s->dh > s->d || s->dh < 0 || + s->dl < 0 || s->dl > s->dh || s->planes < 0 || s->planes > 255) + return; + + /* ensure correct zero padding of bitmap at the final byte of each line */ + if (s->xd & 7) { + bpl = (s->xd + 7) / 8; /* bytes per line */ + for (plane = 0; plane < s->planes; plane++) + for (y = 0; y < s->yd; y++) + s->lhp[0][plane][y * bpl + bpl - 1] &= ~((1 << (8 - (s->xd & 7))) - 1); + } + + /* calculate number of stripes that will be required */ + s->stripes = ((s->yd >> s->d) + + ((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0; + + /* allocate buffers for SDE pointers */ + if (s->sde == NULL) { + s->sde = (struct jbg_buf ****) + checked_malloc(s->stripes * sizeof(struct jbg_buf ***)); + for (stripe = 0; stripe < s->stripes; stripe++) { + s->sde[stripe] = (struct jbg_buf ***) + checked_malloc((s->d + 1) * sizeof(struct jbg_buf **)); + for (layer = 0; layer < s->d + 1; layer++) { + s->sde[stripe][layer] = (struct jbg_buf **) + checked_malloc(s->planes * sizeof(struct jbg_buf *)); + for (plane = 0; plane < s->planes; plane++) + s->sde[stripe][layer][plane] = SDE_TODO; + } + } + } + + /* output BIH */ + bih[0] = s->dl; + bih[1] = s->dh; + bih[2] = s->planes; + bih[3] = 0; + xd = jbg_ceil_half(s->xd, s->d - s->dh); + yd = jbg_ceil_half(s->yd, s->d - s->dh); + bih[4] = xd >> 24; + bih[5] = (xd >> 16) & 0xff; + bih[6] = (xd >> 8) & 0xff; + bih[7] = xd & 0xff; + bih[8] = yd >> 24; + bih[9] = (yd >> 16) & 0xff; + bih[10] = (yd >> 8) & 0xff; + bih[11] = yd & 0xff; + bih[12] = s->l0 >> 24; + bih[13] = (s->l0 >> 16) & 0xff; + bih[14] = (s->l0 >> 8) & 0xff; + bih[15] = s->l0 & 0xff; + bih[16] = s->mx; + bih[17] = s->my; + bih[18] = s->order; + bih[19] = s->options & 0x7f; + s->data_out(bih, 20, s->file); + if ((s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) == + (JBG_DPON | JBG_DPPRIV)) { + /* write private table */ + jbg_int2dppriv(dpbuf, s->dppriv); + s->data_out(dpbuf, 1728, s->file); + } + +#if 0 + /* + * Encode everything first. This is a simple-minded alternative to + * all the tricky on-demand encoding logic in output_sde() for + * debugging purposes. + */ + for (layer = s->dh; layer >= s->dl; layer--) { + for (plane = 0; plane < s->planes; plane++) { + if (layer > 0) + resolution_reduction(s, plane, layer); + for (stripe = 0; stripe < s->stripes; stripe++) + encode_sde(s, stripe, layer, plane); + s->highres[plane] ^= 1; + } + } +#endif + + /* + * Generic loops over all SDEs. Which loop represents layer, plane and + * stripe depends on the option flags. + */ + + /* start and end value vor each loop */ + is[index[order][STRIPE]] = 0; + ie[index[order][STRIPE]] = s->stripes - 1; + is[index[order][LAYER]] = s->dl; + ie[index[order][LAYER]] = s->dh; + is[index[order][PLANE]] = 0; + ie[index[order][PLANE]] = s->planes - 1; + + for (ii[0] = is[0]; ii[0] <= ie[0]; ii[0]++) + for (ii[1] = is[1]; ii[1] <= ie[1]; ii[1]++) + for (ii[2] = is[2]; ii[2] <= ie[2]; ii[2]++) { + + stripe = ii[index[order][STRIPE]]; + if (s->order & JBG_HITOLO) + layer = s->dh - (ii[index[order][LAYER]] - s->dl); + else + layer = ii[index[order][LAYER]]; + plane = ii[index[order][PLANE]]; + + output_sde(s, stripe, layer, plane); + + } + + return; +} + + +void jbg_enc_free(struct jbg_enc_state *s) +{ + unsigned long stripe; + int layer, plane; + +#ifdef DEBUG + fprintf(stderr, "jbg_enc_free(%p)\n", s); +#endif + + /* clear buffers for SDEs */ + if (s->sde) { + for (stripe = 0; stripe < s->stripes; stripe++) { + for (layer = 0; layer < s->d + 1; layer++) { + for (plane = 0; plane < s->planes; plane++) + if (s->sde[stripe][layer][plane] != SDE_DONE && + s->sde[stripe][layer][plane] != SDE_TODO) + jbg_buf_free(&s->sde[stripe][layer][plane]); + checked_free(s->sde[stripe][layer]); + } + checked_free(s->sde[stripe]); + } + checked_free(s->sde); + } + + /* clear free_list */ + jbg_buf_free(&s->free_list); + + /* clear memory for arithmetic encoder states */ + checked_free(s->s); + + /* clear memory for differential-layer typical prediction buffer */ + checked_free(s->tp); + + /* clear memory for adaptive template pixel offsets */ + checked_free(s->tx); + + /* clear lowres image buffers */ + if (s->lhp[1]) { + for (plane = 0; plane < s->planes; plane++) + checked_free(s->lhp[1][plane]); + checked_free(s->lhp[1]); + } + + return; +} + + +/* + * Convert the error codes used by jbg_dec_in() into a string + * written in the selected language and character set. + */ +const char *jbg_strerror(int errnum, int language) +{ + if (errnum < 0 || errnum >= NEMSG) + return "Unknown error code passed to jbg_strerror()"; + if (language < 0 || language >= NEMSG_LANG) + return "Unknown language code passed to jbg_strerror()"; + + return errmsg[language][errnum]; +} + + +/* + * The constructor for a decoder + */ +void jbg_dec_init(struct jbg_dec_state *s) +{ + s->order = 0; + s->d = -1; + s->bie_len = 0; + s->buf_len = 0; + s->dppriv = NULL; + s->xmax = 4294967295UL; + s->ymax = 4294967295UL; + s->dmax = 256; + s->s = NULL; + + return; +} + + +/* + * Specify a maximum image size for the decoder. If the JBIG file has + * the order bit ILEAVE, but not the bit SEQ set, then the decoder + * will abort to decode after the image has reached the maximal + * resolution layer which is still not wider than xmax or higher than + * ymax. + */ +void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax, + unsigned long ymax) +{ + if (xmax > 0) s->xmax = xmax; + if (ymax > 0) s->ymax = ymax; + + return; +} + + +/* + * Decode the new len PSDC bytes to which data points and add them to + * the current stripe. Return the number of bytes which have actually + * been read (this will be less than len if a marker segment was + * part of the data or if the final byte was 0xff were this code + * can not determine, whether we have a marker segment. + */ +static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, + size_t len) +{ + unsigned long stripe; + unsigned int layer, plane; + unsigned long hl, ll, y, hx, hy, lx, ly, hbpl, lbpl; + unsigned char *hp, *lp1, *lp2, *p1, *q1; + register unsigned long line_h1, line_h2, line_h3; + register unsigned long line_l1, line_l2, line_l3; + struct jbg_ardec_state *se; + unsigned long x; + int n; + int pix, cx = 0, slntp, shift, tx; + + /* SDE loop variables */ + stripe = s->ii[index[s->order & 7][STRIPE]]; + layer = s->ii[index[s->order & 7][LAYER]]; + plane = s->ii[index[s->order & 7][PLANE]]; + + /* forward data to arithmetic decoder */ + se = s->s[plane] + layer - s->dl; + se->pscd_ptr = data; + se->pscd_end = data + len; + + /* number of lines per stripe in highres image */ + hl = s->l0 << layer; + /* number of lines per stripe in lowres image */ + ll = hl >> 1; + /* current line number in highres image */ + y = stripe * hl + s->i; + /* number of pixels in highres image */ + hx = jbg_ceil_half(s->xd, s->d - layer); + hy = jbg_ceil_half(s->yd, s->d - layer); + /* number of pixels in lowres image */ + lx = jbg_ceil_half(hx, 1); + ly = jbg_ceil_half(hy, 1); + /* bytes per line in highres and lowres image */ + hbpl = (hx + 7) / 8; + lbpl = (lx + 7) / 8; + /* pointer to highres and lowres image bytes */ + hp = s->lhp[ layer & 1][plane] + (stripe * hl + s->i) * hbpl + + (s->x >> 3); + lp2 = s->lhp[(layer-1) & 1][plane] + (stripe * ll + (s->i >> 1)) * lbpl + + (s->x >> 4); + lp1 = lp2 + lbpl; + + /* restore a few local variables */ + line_h1 = s->line_h1; + line_h2 = s->line_h2; + line_h3 = s->line_h3; + line_l1 = s->line_l1; + line_l2 = s->line_l2; + line_l3 = s->line_l3; + x = s->x; + + if (s->x == 0 && s->i == 0 && + (stripe == 0 || s->reset[plane][layer - s->dl])) { + s->tx[plane][layer - s->dl] = s->ty[plane][layer - s->dl] = 0; + if (s->pseudo) + s->lntp[plane][layer - s->dl] = 1; + } + +#ifdef DEBUG + if (s->x == 0 && s->i == 0 && s->pseudo) + fprintf(stderr, "decode_pscd(%p, %p, %ld): s/d/p = %2lu/%2u/%2u\n", + s, data, (long) len, stripe, layer, plane); +#endif + + if (layer == 0) { + + /* + * Decode lowest resolution layer + */ + + for (; s->i < hl && y < hy; s->i++, y++) { + + /* adaptive template changes */ + if (x == 0) + for (n = 0; n < s->at_moves; n++) + if (s->at_line[n] == s->i) { + s->tx[plane][layer - s->dl] = s->at_tx[n]; + s->ty[plane][layer - s->dl] = s->at_ty[n]; +#ifdef DEBUG + fprintf(stderr, "ATMOVE: line=%lu, tx=%d, ty=%d.\n", s->i, + s->tx[plane][layer - s->dl], s->ty[plane][layer - s->dl]); +#endif + } + tx = s->tx[plane][layer - s->dl]; + shift = tx - ((s->options & JBG_LRLTWO) ? 5 : 3); + + /* typical prediction */ + if (s->options & JBG_TPBON && s->pseudo) { + slntp = arith_decode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + s->lntp[plane][layer - s->dl] = + !(slntp ^ s->lntp[plane][layer - s->dl]); + if (s->lntp[plane][layer - s->dl]) { + /* this line is 'not typical' and has to be coded completely */ + s->pseudo = 0; + } else { + /* this line is 'typical' (i.e. identical to the previous one) */ + p1 = hp; + if (s->i == 0 && (stripe == 0 || s->reset[plane][layer - s->dl])) + while (p1 < hp + hbpl) *p1++ = 0; + else { + q1 = hp - hbpl; + while (q1 < hp) *p1++ = *q1++; + } + hp += hbpl; + continue; + } + } + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the neighbour pixels of the currently decoded pixel X: + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 76543210 76543210 line_h2 + * 76543210 76543210 76543210 76543210 X line_h1 + */ + + if (x == 0) { + line_h1 = line_h2 = line_h3 = 0; + if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) + line_h2 = (long)*(hp - hbpl) << 8; + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 = (long)*(hp - hbpl - hbpl) << 8; + } + + /* + * Another tiny JBIG standard bug: + * + * While implementing the line_h3 handling here, I discovered + * another problem with the ITU-T T.82(1993 E) specification. + * This might be a somewhat pathological case, however. The + * standard is unclear about how a decoder should behave in the + * following situation: + * + * Assume we are in layer 0 and all stripes are single lines + * (L0=1 allowed by table 9). We are now decoding the first (and + * only) line of the third stripe. Assume, the first stripe was + * terminated by SDRST and the second stripe was terminated by + * SDNORM. While decoding the only line of the third stripe with + * the three-line template, we need access to pixels from the + * previous two stripes. We know that the previous stripe + * terminated with SDNROM, so we access the pixel from the + * second stripe. But do we have to replace the pixels from the + * first stripe by background pixels, because this stripe ended + * with SDRST? The standard, especially clause 6.2.5 does never + * mention this case, so the behaviour is undefined here. My + * current implementation remembers only the marker used to + * terminate the previous stripe. In the above example, the + * pixels of the first stripe are accessed despite the fact that + * this stripe ended with SDRST. An alternative (only slightly + * more complicated) implementation would be to remember the end + * marker (SDNORM or SDRST) of the previous two stripes in a + * plane/layer and to act accordingly when accessing the two + * previous lines. What am I supposed to do here? + * + * As the standard is unclear about the correct behaviour in the + * situation of the above example, I strongly suggest to avoid + * the following situation while encoding data with JBIG: + * + * LRLTWO = 0, L0=1 and both SDNORM and SDRST appear in layer 0. + * + * I guess that only a very few if any encoders will switch + * between SDNORM and SDRST, so let us hope that this ambiguity + * in the standard will never cause any interoperability + * problems. + * + * Markus Kuhn -- 1995-04-30 + */ + + /* decode line */ + while (x < hx) { + if ((x & 7) == 0) { + if (x < hbpl * 8 - 8 && + (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl]))) { + line_h2 |= *(hp - hbpl + 1); + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 |= *(hp - hbpl - hbpl + 1); + } + } + if (s->options & JBG_LRLTWO) { + /* two line template */ + do { + if (tx) + pix = arith_decode(se, (((line_h2 >> 9) & 0x3e0) | + ((line_h1 >> shift) & 0x010) | + (line_h1 & 0x00f))); + else + pix = arith_decode(se, (((line_h2 >> 9) & 0x3f0) | + (line_h1 & 0x00f))); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + line_h1 = (line_h1 << 1) | pix; + line_h2 <<= 1; + } while ((++x & 7) && x < hx); + } else { + /* three line template */ + do { + if (tx) + pix = arith_decode(se, (((line_h3 >> 7) & 0x380) | + ((line_h2 >> 11) & 0x078) | + ((line_h1 >> shift) & 0x004) | + (line_h1 & 0x003))); + else + pix = arith_decode(se, (((line_h3 >> 7) & 0x380) | + ((line_h2 >> 11) & 0x07c) | + (line_h1 & 0x003))); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + + line_h1 = (line_h1 << 1) | pix; + line_h2 <<= 1; + line_h3 <<= 1; + } while ((++x & 7) && x < hx); + } /* if (s->options & JBG_LRLTWO) */ + *hp++ = line_h1; + } /* while */ + *(hp - 1) <<= hbpl * 8 - hx; + x = 0; + s->pseudo = 1; + } /* for (i = ...) */ + + } else { + + /* + * Decode differential layer + */ + + for (; s->i < hl && y < hy; s->i++, y++) { + + /* adaptive template changes */ + if (x == 0) + for (n = 0; n < s->at_moves; n++) + if (s->at_line[n] == s->i) { + s->tx[plane][layer - s->dl] = s->at_tx[n]; + s->ty[plane][layer - s->dl] = s->at_ty[n]; +#ifdef DEBUG + fprintf(stderr, "ATMOVE: line=%lu, tx=%d, ty=%d.\n", s->i, + s->tx[plane][layer - s->dl], s->ty[plane][layer - s->dl]); +#endif + } + tx = s->tx[plane][layer - s->dl]; + shift = tx - 3; + + /* handle lower border of low-resolution image */ + if ((s->i >> 1) >= ll - 1 || (y >> 1) >= ly - 1) + lp1 = lp2; + + /* typical prediction */ + if (s->options & JBG_TPDON && s->pseudo) { + s->lntp[plane][layer - s->dl] = arith_decode(se, TPDCX); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + s->pseudo = 0; + } + + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the high resolution neighbour pixels of the currently + * decoded highres pixel X: + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 76543210 76543210 line_h2 + * 76543210 76543210 76543210 76543210 X line_h1 + * + * Layout of the variables line_l1, line_l2, line_l3, which contain + * the low resolution pixels near the currently decoded pixel as bits. + * The lowres pixel in which the currently coded highres pixel is + * located is marked as Y: + * + * 76543210 76543210 76543210 76543210 line_l3 + * 76543210 76543210 Y6543210 76543210 line_l2 + * 76543210 76543210 76543210 76543210 line_l1 + */ + + + if (x == 0) { + line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0; + if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) { + line_h2 = (long)*(hp - hbpl) << 8; + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 = (long)*(hp - hbpl - hbpl) << 8; + } + if (s->i > 1 || (y > 1 && !s->reset[plane][layer-s->dl])) + line_l3 = (long)*(lp2 - lbpl) << 8; + line_l2 = (long)*lp2 << 8; + line_l1 = (long)*lp1 << 8; + } + + /* decode line */ + while (x < hx) { + if ((x & 15) == 0) + if ((x >> 1) < lbpl * 8 - 8) { + line_l1 |= *(lp1 + 1); + line_l2 |= *(lp2 + 1); + if (s->i > 1 || + (y > 1 && !s->reset[plane][layer - s->dl])) + line_l3 |= *(lp2 - lbpl + 1); + } + do { + + assert(hp - (s->lhp[ layer &1][plane] + (stripe * hl + s->i) + * hbpl) == (ptrdiff_t) x >> 3); + assert(lp2 - (s->lhp[(layer-1) &1][plane] + (stripe * ll + (s->i>>1)) + * lbpl) == (ptrdiff_t) x >> 4); + + if ((x & 7) == 0) + if (x < hbpl * 8 - 8) { + if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) { + line_h2 |= *(hp + 1 - hbpl); + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 |= *(hp + 1 - hbpl - hbpl); + } + } + do { + if (!s->lntp[plane][layer - s->dl]) + cx = (((line_l3 >> 14) & 0x007) | + ((line_l2 >> 11) & 0x038) | + ((line_l1 >> 8) & 0x1c0)); + if (!s->lntp[plane][layer - s->dl] && + (cx == 0x000 || cx == 0x1ff)) { + /* pixels are typical and have not to be decoded */ + do { + line_h1 = (line_h1 << 1) | (cx & 1); + } while ((++x & 1) && x < hx); + line_h2 <<= 2; line_h3 <<= 2; + } else + do { + + /* deterministic prediction */ + if (s->options & JBG_DPON) + if ((y & 1) == 0) + if ((x & 1) == 0) + /* phase 0 */ + pix = s->dppriv[((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x010) | + ((line_h2 >> 9) & 0x0e0)]; + else + /* phase 1 */ + pix = s->dppriv[(((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x030) | + ((line_h2 >> 9) & 0x1c0)) + 256]; + else + if ((x & 1) == 0) + /* phase 2 */ + pix = s->dppriv[(((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x010) | + ((line_h2 >> 9) & 0x0e0) | + ((line_h3 >> 6) & 0x700)) + 768]; + else + /* phase 3 */ + pix = s->dppriv[(((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x030) | + ((line_h2 >> 9) & 0x1c0) | + ((line_h3 >> 6) & 0xe00)) + 2816]; + else + pix = 2; + + if (pix & 2) { + if (tx) + cx = ((line_h1 & 0x003) | + (((line_h1 << 2) >> shift) & 0x010) | + ((line_h2 >> 12) & 0x00c) | + ((line_h3 >> 10) & 0x020)); + else + cx = ((line_h1 & 0x003) | + ((line_h2 >> 12) & 0x01c) | + ((line_h3 >> 10) & 0x020)); + if (x & 1) + cx |= (((line_l2 >> 8) & 0x0c0) | + ((line_l1 >> 6) & 0x300)) | (1UL << 10); + else + cx |= (((line_l2 >> 9) & 0x0c0) | + ((line_l1 >> 7) & 0x300)); + cx |= (y & 1) << 11; + + pix = arith_decode(se, cx); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + } + + line_h1 = (line_h1 << 1) | pix; + line_h2 <<= 1; + line_h3 <<= 1; + + } while ((++x & 1) && x < hx); + line_l1 <<= 1; line_l2 <<= 1; line_l3 <<= 1; + } while ((x & 7) && x < hx); + *hp++ = line_h1; + } while ((x & 15) && x < hx); + ++lp1; + ++lp2; + } /* while */ + x = 0; + + *(hp - 1) <<= hbpl * 8 - hx; + if ((s->i & 1) == 0) { + /* low resolution pixels are used twice */ + lp1 -= lbpl; + lp2 -= lbpl; + } else + s->pseudo = 1; + + } /* for (i = ...) */ + + } + + leave: + + /* save a few local variables */ + s->line_h1 = line_h1; + s->line_h2 = line_h2; + s->line_h3 = line_h3; + s->line_l1 = line_l1; + s->line_l2 = line_l2; + s->line_l3 = line_l3; + s->x = x; + + return se->pscd_ptr - data; +} + + +/* + * Provide a new BIE fragment to the decoder. + * + * If cnt is not NULL, then *cnt will contain after the call the + * number of actually read bytes. If the data was not complete, then + * the return value will be JBG_EAGAIN and *cnt == len. In case this + * function has returned with JBG_EOK, then it has reached the end of + * a BIE but it can be called again with data from the next BIE if + * there exists one in order to get to a higher resolution layer. In + * case the return value was JBG_EOK_INTR then this function can be + * called again with the rest of the BIE, because parsing the BIE has + * been interrupted by a jbg_dec_maxsize() specification. In both + * cases the remaining len - *cnt bytes of the previous block will + * have to passed to this function again (if len > *cnt). In case of + * any other return value than JBG_EOK, JBG_EOK_INTR or JBG_EAGAIN, a + * serious problem has occured and the only function you should call + * is jbg_dec_free() in order to remove the mess (and probably + * jbg_strerror() in order to find out what to tell the user). + */ +int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, + size_t *cnt) +{ + int i, j, required_length; + unsigned long x, y; + unsigned long is[3], ie[3]; + long hsize, lsize; + extern char jbg_dptable[]; + size_t dummy_cnt; + + if (!cnt) cnt = &dummy_cnt; + *cnt = 0; + if (len < 1) return JBG_EAGAIN; + + /* read in 20-byte BIH */ + if (s->bie_len < 20) { + while (s->bie_len < 20 && *cnt < len) + s->buffer[s->bie_len++] = data[(*cnt)++]; + if (s->bie_len < 20) + return JBG_EAGAIN; + if (s->buffer[1] < s->buffer[0]) + return JBG_EINVAL; + /* test whether this looks like a valid JBIG header at all */ + if (s->buffer[3] != 0 || (s->buffer[18] & 0xf0) != 0 || + (s->buffer[19] & 0x80) != 0) + return JBG_EINVAL; + if (s->buffer[0] != s->d + 1) + return JBG_ENOCONT; + s->dl = s->buffer[0]; + s->d = s->buffer[1]; + if (s->dl == 0) + s->planes = s->buffer[2]; + else + if (s->planes != s->buffer[2]) + return JBG_ENOCONT; + x = (((long) s->buffer[ 4] << 24) | ((long) s->buffer[ 5] << 16) | + ((long) s->buffer[ 6] << 8) | (long) s->buffer[ 7]); + y = (((long) s->buffer[ 8] << 24) | ((long) s->buffer[ 9] << 16) | + ((long) s->buffer[10] << 8) | (long) s->buffer[11]); + if (s->dl != 0 && ((s->xd << (s->d - s->dl + 1)) != x && + (s->yd << (s->d - s->dl + 1)) != y)) + return JBG_ENOCONT; + s->xd = x; + s->yd = y; + s->l0 = (((long) s->buffer[12] << 24) | ((long) s->buffer[13] << 16) | + ((long) s->buffer[14] << 8) | (long) s->buffer[15]); + if (!s->planes || !s->xd || !s->yd || !s->l0) + return JBG_EINVAL; + s->mx = s->buffer[16]; + if (s->mx > 127) + return JBG_EINVAL; + s->my = s->buffer[17]; + if (s->mx > 32 || s->my > 0) + return JBG_EIMPL; + s->order = s->buffer[18]; + if (index[s->order & 7][0] < 0) + return JBG_EINVAL; + /* HITOLO and SEQ currently not yet implemented */ + if (s->dl != s->d && (s->order & JBG_HITOLO || s->order & JBG_SEQ)) + return JBG_EIMPL; + s->options = s->buffer[19]; + + /* calculate number of stripes that will be required */ + s->stripes = ((s->yd >> s->d) + + ((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0; + + /* some initialization */ + s->ii[index[s->order & 7][STRIPE]] = 0; + s->ii[index[s->order & 7][LAYER]] = s->dl; + s->ii[index[s->order & 7][PLANE]] = 0; + /* bytes required for resolution layer D and D-1 */ + hsize = ((s->xd + 7) / 8) * s->yd; + lsize = ((jbg_ceil_half(s->xd, 1) + 7) / 8) * + jbg_ceil_half(s->yd, 1); + if (s->dl == 0) { + s->s = checked_malloc(s->planes * sizeof(struct jbg_ardec_state *)); + s->tx = checked_malloc(s->planes * sizeof(int *)); + s->ty = checked_malloc(s->planes * sizeof(int *)); + s->reset = checked_malloc(s->planes * sizeof(int *)); + s->lntp = checked_malloc(s->planes * sizeof(int *)); + s->lhp[0] = checked_malloc(s->planes * sizeof(unsigned char *)); + s->lhp[1] = checked_malloc(s->planes * sizeof(unsigned char *)); + for (i = 0; i < s->planes; i++) { + s->s[i] = checked_malloc((s->d - s->dl + 1) * + sizeof(struct jbg_ardec_state)); + s->tx[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int)); + s->ty[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int)); + s->reset[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int)); + s->lntp[i] = checked_malloc((s->d - s->dl + 1) * sizeof(int)); + s->lhp[s->d &1][i] = checked_malloc(sizeof(unsigned char) * hsize); + s->lhp[(s->d-1)&1][i] = checked_malloc(sizeof(unsigned char) * lsize); + } + } else { + for (i = 0; i < s->planes; i++) { + s->s[i] = checked_realloc(s->s[i], (s->d - s->dl + 1) * + sizeof(struct jbg_ardec_state)); + s->tx[i] = checked_realloc(s->tx[i], (s->d - s->dl + 1) * sizeof(int)); + s->ty[i] = checked_realloc(s->ty[i], (s->d - s->dl + 1) * sizeof(int)); + s->reset[i] = checked_realloc(s->reset[i], + (s->d - s->dl +1) * sizeof(int)); + s->lntp[i] = checked_realloc(s->lntp[i], + (s->d - s->dl +1) * sizeof(int)); + s->lhp[s->d &1][i] = checked_realloc(s->lhp[s->d & 1][i], + sizeof(unsigned char) * hsize); + s->lhp[(s->d-1)&1][i] = checked_realloc(s->lhp[(s->d-1)&1][i], + sizeof(unsigned char) * lsize); + } + } + for (i = 0; i < s->planes; i++) + for (j = 0; j <= s->d - s->dl; j++) + arith_decode_init(s->s[i] + j, 0); + if (s->dl == 0 || (s->options & JBG_DPON && !(s->options & JBG_DPPRIV))) + s->dppriv = jbg_dptable; + s->comment_skip = 0; + s->buf_len = 0; + s->x = 0; + s->i = 0; + s->pseudo = 1; + s->at_moves = 0; + } + + /* read in DPTABLE */ + if (s->bie_len < 20 + 1728 && + (s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) == + (JBG_DPON | JBG_DPPRIV)) { + assert(s->bie_len >= 20); + while (s->bie_len < 20 + 1728 && *cnt < len) + s->buffer[s->bie_len++ - 20] = data[(*cnt)++]; + if (s->bie_len < 20 + 1728) + return JBG_EAGAIN; + if (!s->dppriv || s->dppriv == jbg_dptable) + s->dppriv = checked_malloc(sizeof(char) * 1728); + jbg_dppriv2int(s->dppriv, s->buffer); + } + + /* + * BID processing loop + */ + + while (*cnt < len) { + + /* process floating marker segments */ + + /* skip COMMENT contents */ + if (s->comment_skip) { + if (s->comment_skip <= len - *cnt) { + *cnt += s->comment_skip; + s->comment_skip = 0; + } else { + s->comment_skip -= len - *cnt; + *cnt = len; + } + continue; + } + + /* load complete marker segments into s->buffer for processing */ + if (s->buf_len > 0) { + assert(s->buffer[0] == MARKER_ESC); + while (s->buf_len < 2 && *cnt < len) + s->buffer[s->buf_len++] = data[(*cnt)++]; + if (s->buf_len < 2) continue; + switch (s->buffer[1]) { + case MARKER_COMMENT: required_length = 6; break; + case MARKER_ATMOVE: required_length = 8; break; + case MARKER_NEWLEN: required_length = 6; break; + case MARKER_ABORT: + case MARKER_SDNORM: + case MARKER_SDRST: required_length = 2; break; + case MARKER_STUFF: + /* forward stuffed 0xff to arithmetic decoder */ + s->buf_len = 0; + decode_pscd(s, s->buffer, 2); + continue; + default: + return JBG_EMARKER; + } + while (s->buf_len < required_length && *cnt < len) + s->buffer[s->buf_len++] = data[(*cnt)++]; + if (s->buf_len < required_length) continue; + /* now the buffer is filled with exactly one marker segment */ + switch (s->buffer[1]) { + case MARKER_COMMENT: + s->comment_skip = + (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) | + ((long) s->buffer[4] << 8) | (long) s->buffer[5]); + break; + case MARKER_ATMOVE: + if (s->at_moves < JBG_ATMOVES_MAX) { + s->at_line[s->at_moves] = + (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) | + ((long) s->buffer[4] << 8) | (long) s->buffer[5]); + s->at_tx[s->at_moves] = (signed char) s->buffer[6]; + s->at_ty[s->at_moves] = s->buffer[7]; + if (s->at_tx[s->at_moves] < - (int) s->mx || + s->at_tx[s->at_moves] > (int) s->mx || + s->at_ty[s->at_moves] > (int) s->my || + (s->at_ty[s->at_moves] == 0 && s->at_tx[s->at_moves] < 0)) + return JBG_EINVAL; + s->at_moves++; + } else + return JBG_EINVAL; + break; + case MARKER_NEWLEN: + y = (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) | + ((long) s->buffer[4] << 8) | (long) s->buffer[5]); + if (y > s->yd || !(s->options & JBG_VLENGTH)) + return JBG_EINVAL; + s->yd = y; + /* calculate again number of stripes that will be required */ + s->stripes = + ((s->yd >> s->d) + + ((((1UL << s->d) - 1) & s->xd) != 0) + s->l0 - 1) / s->l0; + break; + case MARKER_ABORT: + return JBG_EABORT; + + case MARKER_SDNORM: + case MARKER_SDRST: + /* decode final pixels based on trailing zero bytes */ + decode_pscd(s, s->buffer, 2); + + arith_decode_init(s->s[s->ii[index[s->order & 7][PLANE]]] + + s->ii[index[s->order & 7][LAYER]] - s->dl, + s->ii[index[s->order & 7][STRIPE]] != s->stripes - 1 + && s->buffer[1] != MARKER_SDRST); + + s->reset[s->ii[index[s->order & 7][PLANE]]] + [s->ii[index[s->order & 7][LAYER]] - s->dl] = + (s->buffer[1] == MARKER_SDRST); + + /* prepare for next SDE */ + s->x = 0; + s->i = 0; + s->pseudo = 1; + s->at_moves = 0; + + /* increment layer/stripe/plane loop variables */ + /* start and end value for each loop: */ + is[index[s->order & 7][STRIPE]] = 0; + ie[index[s->order & 7][STRIPE]] = s->stripes - 1; + is[index[s->order & 7][LAYER]] = s->dl; + ie[index[s->order & 7][LAYER]] = s->d; + is[index[s->order & 7][PLANE]] = 0; + ie[index[s->order & 7][PLANE]] = s->planes - 1; + i = 2; /* index to innermost loop */ + do { + j = 0; /* carry flag */ + if (++s->ii[i] > ie[i]) { + /* handling overflow of loop variable */ + j = 1; + if (i > 0) + s->ii[i] = is[i]; + } + } while (--i >= 0 && j); + + s->buf_len = 0; + + /* check whether this have been all SDEs */ + if (j) { + s->bie_len = 0; + return JBG_EOK; + } + + /* check whether we have to abort because of xmax/ymax */ + if (index[s->order & 7][LAYER] == 0 && i < 0) { + /* LAYER is the outermost loop and we have just gone to next layer */ + if (jbg_ceil_half(s->xd, s->d - s->ii[0]) > s->xmax || + jbg_ceil_half(s->yd, s->d - s->ii[0]) > s->ymax) { + s->xmax = 4294967295UL; + s->ymax = 4294967295UL; + return JBG_EOK_INTR; + } + if (s->ii[0] > (unsigned long) s->dmax) { + s->dmax = 256; + return JBG_EOK_INTR; + } + } + + break; + } + s->buf_len = 0; + + } else if (data[*cnt] == MARKER_ESC) + s->buffer[s->buf_len++] = data[(*cnt)++]; + + else { + + /* we have found PSCD bytes */ + *cnt += decode_pscd(s, data + *cnt, len - *cnt); + if (*cnt < len && data[*cnt] != 0xff) { +#ifdef DEBUG + fprintf(stderr, "PSCD was longer than expected, unread bytes " + "%02x %02x %02x %02x ...\n", data[*cnt], data[*cnt+1], + data[*cnt+2], data[*cnt+3]); +#endif + return JBG_EINVAL; + } + + } + } /* of BID processing loop 'while (*cnt < len) ...' */ + + return JBG_EAGAIN; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this + * function in order to find out the width of the image. + */ +long jbg_dec_getwidth(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (index[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)); + } + + return s->xd; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this + * function in order to find out the height of the image. + */ +long jbg_dec_getheight(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (index[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); + } + + return s->yd; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this + * function in order to get a pointer to the image. + */ +unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane) +{ + if (s->d < 0) + return NULL; + if (index[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return NULL; + else + return s->lhp[(s->ii[0] - 1) & 1][plane]; + } + + return s->lhp[s->d & 1][plane]; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call + * this function in order to find out the size in bytes of one + * bitplane of the image. + */ +long jbg_dec_getsize(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (index[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return + ((jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) + 7) / 8) * + jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); + } + + return ((s->xd + 7) / 8) * s->yd; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call + * this function in order to find out the size of the image that you + * can retrieve with jbg_merge_planes(). + */ +long jbg_dec_getsize_merged(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (index[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return + jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) * + jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)) * + ((s->planes + 7) / 8); + } + + return s->xd * s->yd * ((s->planes + 7) / 8); +} + + +/* + * The destructor function which releases any resources obtained by the + * other decoder functions. + */ +void jbg_dec_free(struct jbg_dec_state *s) +{ + int i; + + if (s->d < 0 || s->s == NULL) + return; + s->d = -2; + + for (i = 0; i < s->planes; i++) { + checked_free(s->s[i]); + checked_free(s->tx[i]); + checked_free(s->ty[i]); + checked_free(s->reset[i]); + checked_free(s->lntp[i]); + checked_free(s->lhp[0][i]); + checked_free(s->lhp[1][i]); + } + + checked_free(s->s); + checked_free(s->tx); + checked_free(s->ty); + checked_free(s->reset); + checked_free(s->lntp); + checked_free(s->lhp[0]); + checked_free(s->lhp[1]); + + s->s = NULL; + + return; +} + + +/* + * Split bigendian integer pixel field into separate bit planes. In the + * src array, every pixel is represented by a ((has_planes + 7) / 8) byte + * long word, most significant byte first. While has_planes describes + * the number of used bits per pixel in the source image, encode_plane + * is the number of most significant bits among those that we + * actually transfer to dest. + */ +void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, + int encode_planes, + const unsigned char *src, unsigned char **dest, + int use_graycode) +{ + unsigned bpl = (x + 7) / 8; /* bytes per line in dest plane */ + unsigned i, k = 8; + int p; + unsigned long line; + extern void *memset(void *s, int c, size_t n); + unsigned prev; /* previous *src byte shifted by 8 bit to the left */ + register int bits, msb = has_planes - 1; + int bitno; + + /* sanity checks */ + if (encode_planes > has_planes) + encode_planes = has_planes; + use_graycode = use_graycode != 0 && encode_planes > 1; + + for (p = 0; p < encode_planes; p++) + memset(dest[p], 0, bpl * y); + + for (line = 0; line < y; line++) { /* lines loop */ + for (i = 0; i * 8 < x; i++) { /* dest bytes loop */ + for (k = 0; k < 8 && i * 8 + k < x; k++) { /* pixel loop */ + prev = 0; + for (p = 0; p < encode_planes; p++) { /* bit planes loop */ + /* calculate which bit in *src do we want */ + bitno = (msb - p) & 7; + /* put this bit with its left neighbor right adjusted into bits */ + bits = (prev | *src) >> bitno; + /* go to next *src byte, but keep old */ + if (bitno == 0) + prev = *src++; + /* make space for inserting new bit */ + dest[p][bpl * line + i] <<= 1; + /* insert bit, if requested apply Gray encoding */ + dest[p][bpl * line + i] |= (bits ^ (use_graycode & (bits>>1))) & 1; + /* + * Theorem: Let b(n),...,b(1),b(0) be the digits of a + * binary word and let g(n),...,g(1),g(0) be the digits of the + * corresponding Gray code word, then g(i) = b(i) xor b(i+1). + */ + } + /* skip unused *src bytes */ + for (;p < has_planes; p++) + if (((has_planes - 1 - p) & 7) == 0) + src++; + } + } + for (p = 0; p < encode_planes; p++) /* right padding loop */ + dest[p][bpl * (line + 1) - 1] <<= 8 - k; + } + + return; +} + +/* + * Merge the separate bit planes decoded by the JBIG decoder into an + * integer pixel field. This is essentially the counterpart to + * jbg_split_planes(). */ +void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, + void (*data_out)(unsigned char *start, size_t len, + void *file), void *file) +{ +#define BUFLEN 4096 + int bpp, bpl; + unsigned long line; + unsigned i, k = 8; + int p, q; + unsigned char buf[BUFLEN]; + unsigned char *bp = buf; + unsigned char **src; + unsigned long x, y; + unsigned v; + + /* sanity check */ + use_graycode = use_graycode != 0; + + x = jbg_dec_getwidth(s); + y = jbg_dec_getheight(s); + if (x <= 0 || y <= 0) + return; + bpp = (s->planes + 7) / 8; /* bytes per pixel in dest image */ + bpl = (x + 7) / 8; /* bytes per line in src plane */ + + if (index[s->order & 7][LAYER] == 0) + if (s->ii[0] < 1) + return; + else + src = s->lhp[(s->ii[0] - 1) & 1]; + else + src = s->lhp[s->d & 1]; + + for (line = 0; line < y; line++) { /* lines loop */ + for (i = 0; i * 8 < x; i++) { /* src bytes loop */ + for (k = 0; k < 8 && i * 8 + k < x; k++) { /* pixel loop */ + for (p = (s->planes-1) & ~7; p >= 0; p -= 8) { /* dest bytes loop */ + v = 0; + for (q = 0; q < 8 && p+q < s->planes; q++) /* pixel bit loop */ + v = (v << 1) | + (((src[p+q][bpl * line + i] >> (7 - k)) & 1) ^ + (use_graycode & v)); + *bp++ = v; + if (bp - buf == BUFLEN) { + data_out(buf, BUFLEN, file); + bp = buf; + } + } + } + } + } + + if (bp - buf > 0) + data_out(buf, bp - buf, file); + + return; +} diff --git a/converter/other/jbig/jbig.doc b/converter/other/jbig/jbig.doc new file mode 100644 index 00000000..10eeda80 --- /dev/null +++ b/converter/other/jbig/jbig.doc @@ -0,0 +1,721 @@ + +Using the JBIG-KIT library +-------------------------- + +Markus Kuhn -- 1998-04-10 + + +This text explains how to include the functions provided by the +JBIG-KIT portable image compression library into your application +software. + + +1 Introduction to JBIG + +Below follows a short introduction into some technical aspects of the +JBIG standard. More detailed information is provided in the +"Introduction and overview" section of the JBIG standard. Information +about how to obtain a copy of the standard is available on the +Internet from or . + +Image data encoded with the JBIG algorithm is separated into planes, +layers, and stripes. Each plane contains one bit per pixel. The number +of planes stored in a JBIG data stream is the number of bits per +pixel. Resolution layers are numbered from 0 to D with 0 being the +layer with the lowest resolution and D the layer with the highest one. +Each next higher resolution layer has exactly twice the number of rows +and columns than the previous one. Layer 0 is encoded independently of +any other data, all other resolution layers are encoded as only the +difference between the next lower and the current layer. For +applications that require very quick access to parts of an image it is +possible to divide an image into several horizontal stripes. All +stripes of one resolution layer have equal size except perhaps the +final one. The number of stripes of an image is equal in all +resolution layers and in all bit planes. + +The compressed data stream specified by the JBIG standard is called a +bi-level image entity (BIE). A BIE consists of a 20-byte header, +followed by an optional 1728-byte table (usually not present, except +in special applications) followed by a sequence of stripe data +entities (SDE). SDEs are the data blocks of which each encodes the +content of one single stripe in one plane and resolution layer. +Between the SDEs, other information blocks (called floating marker +segments) can also be present, which change certain parameters of the +algorithm in the middle of an image or contain additional application +specific information. A BIE looks like this: + + + +------------------------------------------------+ + | | + | 20-byte header (with image size, #planes, | + | #layers, stripe size, first layer, options, | + | SDE ordering, ...) | + | | + +------------------------------------------------+ + | | + | optional 1728-byte table | + | | + +------------------------------------------------+ + | | + | stripe data entity | + | | + +------------------------------------------------+ + | | + | optional floating marker segments | + | | + +------------------------------------------------+ + | | + | stripe data entity | + | | + +------------------------------------------------+ + ... + +------------------------------------------------+ + | | + | stripe data entity | + | | + +------------------------------------------------+ + + +One BIE can contain all resolution layers of an image, but it is also +possible to store various resolution layers in several BIEs. The BIE +header contains the number of the first and the last resolution layer +stored in this BIE, as well as the size of the highest resolution +layer stored in this BIE. Progressive coding is deactivated by simply +storing the image in one single resolution layer. + +Different applications might have different requirements for the order +in which the SDEs for stripes of various planes and layers are stored +in the BIE, so all possible sensible orderings are allowed and +indicated by four bits in the header. + +It is possible to use the raw BIE data stream as specified by the JBIG +standard directly as the format of a file used for storing images. +This is what the JBIG<->PBM conversion tools that are provided in this +package as demonstration applications do. However as the BIE format +has been designed for a large number of very different applications +and also in order to allow efficient direct processing by special JBIG +hardware chip implementations, the BIE header contains only the +minimum amount of information absolutely required by the decompression +algorithm. A large number of features expected from a good file format +are missing in the BIE data stream: + + - no "magic code" in the first few bytes to allow identification + of the file on a typeless file system as JBIG encoded and to allow + automatic distinction from other compression algorithms + + - no standardized way to encode additional information like a textual + description, information about the meaning of various bit planes, + the physical size and resolution of the document, etc. + + - a checksum that ensures image integrity + + - encryption and signature mechanisms + + - many things more + +Raw BIE data streams alone are consequently no suitable format for +document archiving and exchange. A standard format for this purpose +would typically combine a BIE representing the image data together +with an additional header providing auxiliary information into one +file. Existing established multi-purpose file formats with a rich set +of auxiliary information attributes like TIFF could be extended easily +so that they can also contain JBIG compressed data. + +On the other hand, in database applications for instance, a BIE might +be directly stored in a variable length field. Auxiliary information +on which efficient search operations are required would then be stored +in other fields of the same record. + + +2 Compressing an image + +2.1 Format of the source image + +For processing by the library, the image has to be present in memory +as separate bitmap planes. Each byte of a bitmap contains eight +pixels, the most significant bit represents the leftmost of these +pixels. Each line of a bitmap has to be stored in an integral number +of bytes. If the image width is not an integral multiple of eight, +then the final byte has to be padded with zero bits. + +For example the 23x5 pixels large single plane image: + + .XXXXX..XXX...X...XXX.. + .....X..X..X..X..X..... + .....X..XXX...X..X.XXX. + .X...X..X..X..X..X...X. + ..XXX...XXX...X...XXX.. + +is represented by the 15 bytes + + 01111100 11100010 00111000 + 00000100 10010010 01000000 + 00000100 11100010 01011100 + 01000100 10010010 01000100 + 00111000 11100010 00111000 + +or in hexadecimal notation + + 7c e2 38 04 92 40 04 e2 5c 44 92 44 38 e2 38 + +This is the format used in binary PBM files and it can also be be +handled directly by the Xlib library of the X Window System. + +As JBIG can also handle images with several bit planes, the JBIG-KIT +library functions accept and return always arrays of pointers to +bitmaps with one pointer per plane. + +For single plane images, the standard recommends that a 0 pixel +represents the background and a 1 pixel represents the foreground +color of an image, i.e. 0 is white and 1 is black for scanned paper +documents. For images with several bits per pixel, the JBIG standard +makes no recommendations about how various colors should be encoded. + +For greyscale images, by using a Gray code instead of a simple binary +weighted representation of the pixel intensity, some increase in +coding efficiency can be reached. + +A Gray code is also a binary representation of integer numbers, but +has the property that the representations of the integer numbers i and +(i+1) differ always in exactly one single bit. For example, the +numbers 0 to 7 can be represented in normal binary code and Gray code +as in the following table: + + normal + number binary code Gray code + --------------------------------------- + 0 000 000 + 1 001 001 + 2 010 011 + 3 011 010 + 4 100 110 + 5 101 111 + 6 110 101 + 7 111 100 + +The form of Gray code shown above has the property that the second +half of the code (numbers 4 - 7) is simply the mirrored first half +(numbers 3 - 0) with the first bit set to one. This way, arbitrarily +large Gray codes can be generated quickly by mirroring the above +example and prefixing the first half with zeros and the second half +with ones as often as required. In greyscale images, it is common +practise to use the all-0 code for black and the all-1 code for white. + +No matter whether a Gray code or a binary code is used for encoding a +pixel intensity in several bit planes, it always makes sense to store +the most significant (leftmost) bit in plane 0, which is transmitted +first. This way, a decoder could increase the precision of the +displayed pixel intensities while data is still being received and the +basic structure of the image will become visible as early as possible +during the transmission. + + +2.2 A simple compression application + +In order to use JBIG-KIT in your application, just link libjbig.a to +your executable (on Unix systems just add -ljbig and -L. to the +command line options of your compiler, on other systems you will have +to write a new Makefile anyway), copy the file jbig.h into your source +directory and put the line + + #include "jbig.h" + +into your source code. + +The library interface follows the concepts of object-oriented +programming. You have to declare a variable (object) + + struct jbg_enc_state se; + +which contains the current status of an encoder. Then you initialize +the encoder by calling the constructor function + + void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, + int pl, unsigned char **p, + void (*data_out)(unsigned char *start, size_t len, + void *file), + void *file); + +The parameters have the following meaning: + + s A pointer to the jbg_enc_state structure which you want + to initialize. + + x The width of your image. + + y The height of your image. + + pl the number of bitmap planes you want to encode. + + p A pointer to an array of pl pointers, where each is again + pointing to the first byte of a bitmap as described in + section 2.1. + + data_out This is a call-back function which will be called during + the compression process by libjbig in order to deliver + the BIE data to the application. The parameters of the + function data_out are a pointer start to the new block of + data to be delivered as well as the number len of delivered + bytes. The pointer file is transparently delivered to + data_out as specified in jbg_enc_init(). Usually, data_out + will write the BIE portion to a file, send it to a + network connection or append it to some memory buffer. + + file A pointer parameter which is transparently passed to + data_out() and allows data_out() to distinguish by which + compression task it has been called in multi-threaded + applications. + +In the simplest case, the compression is then started by calling the +function + + void jbg_enc_out(struct jbg_enc_state *s); + +which will deliver the complete BIE to data_out(). After this, a call +to the destructor function + + void jbg_enc_free(struct jbg_enc_state *s); + +will release any memory allocated by the previous functions. + + +A minimal example application which sends the BIE of the above example +bitmap to stdout looks like this: + +--------------------------------------------------------------------------- +/* A sample JBIG encoding application */ + +#include +#include "jbig.h" + +void output_bie(unsigned char *start, size_t len, void *file) +{ + fwrite(start, 1, len, (FILE *) file); + + return; +} + +int main() +{ + unsigned char bitmap[15] = { + /* 23 x 5 pixels, "JBIG" */ + 0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2, + 0x5c, 0x44, 0x92, 0x44, 0x38, 0xe2, 0x38 + }; + unsigned char *bitmaps[1] = { bitmap }; + struct jbg_enc_state se; + + jbg_enc_init(&se, 23, 5, 1, bitmaps, + output_bie, stdout); /* initialize encoder */ + jbg_enc_out(&se); /* encode image */ + jbg_enc_free(&se); /* release allocated resources */ + + return 0; +} +--------------------------------------------------------------------------- + +This software produces a 42 byte long BIE. (JBIG is not very good at +compressing extremely small images like in this example, because the +arithmetic encoder requires some startup data in order to generate +reasonable statistics which influence the compression process and +because there is some header overhead.) + + +2.3 More about compression + +If jbg_enc_out() is called directly after jbg_enc_init(), the +following default values are used for various compression parameters: + + - Only one single resolution layer is used, i.e. no progressive + mode. + + - The number of lines per stripe is selected so that approximately + 35 stripes per image are used (as recommended in annex C of the + standard together with the suggested adaptive template change + algorithm). However not less than 2 and not more than 128 lines + are used in order to stay within the suggested minimum parameter + support range specified in annex A of the standard). + + - All optional parts of the JBIG algorithm are activated (TPBON, + TPDON and DPON). + + - The default resolution reduction table and the default deterministic + prediction tables are used + + - The maximal vertical offset of the adaptive template pixel is 0 + and the maximal horizontal offset is 8 (mx = 8, my = 0). + +In order to change any of these default parameters, additional +functions have to be called between jbg_enc_init() and jbg_enc_out(). + +In order to activate progressive encoding, it is possible to specify +with + + void jbg_enc_layers(struct jbg_enc_state *s, int d); + +the number d of differential resolution layers which shall be encoded +in addition to the lowest resolution layer 0. For example, if a 300 +dpi document has to be stored and the lowest resolution layer shall +have 75 dpi so that a screen previewer can directly decompress only +the required resolution, then a call + + jbg_enc_layers(&se, 2); + +will cause three resolution layers with 75, 150 and 300 dots per inch. + +If the application does not know what typical resolutions are used and +simply wants to ensure that the lowest resolution layer will fit into +a given maximal window size, then as an alternative, a call to + + int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth, + unsigned long mheight); + +will cause the library to automatically determine the suitable number +of resolutions so that the lowest resolution layer 0 will not be +larger than mwidth x mheight pixels. E.g. if one wants to ensure that +systems with a 640 x 480 pixel large screen can decode the required +resolution directly, then call + + jbg_enc_lrlmax(&se, 640, 480); + +The return value is the number of differential layers selected. + +After the number of resolution layers has been specified by calls to +jbg_enc_layers() or jbg_enc_lrlmax(), by default all these layers will +be written into the BIE. This can be changed with a call to + + int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh); + +Parameter dl specifies the lowest resolution layer and dh the highest +resolution layer that will appear in the BIE. If e.g. only layer 0 +shall be written to the first BIE and layer 1 and 2 shall be written +to a second one, then before writing the first BIE, one calls + + jbg_enc_lrange(&se, 0, 0); + +and before writing the second BIE with jbg_enc_out(), one calls + + jbg_enc_lrange(&se, 1, 2); + +If any of the parameters is negative, it will be ignored. The return +value is the total number of differential layers which will represent +the input image. This way, jbg_enc_lrange(&se, -1, -1) can be used to +query the layer of the full image. + +A number of other more exotic options of the JBIG algorithm can be +modified by calling + + void jbg_enc_options(struct jbg_enc_state *s, int order, int options, + long l0, int mx, int my); + +before calling jbg_enc_out(). + +The order parameter can be a combination of the bits JBG_HITOLO, +JBG_SEQ, JBG_ILEAVE and JBG_SMID and it determines in which order +the SDEs are stored in the BIE. The bits have the following meaning: + + JBG_HITOLO Usually, the lower resolution layers are stored before + the higher resolution layers, so that a decoder can + already start to display a low resolution version of + the full image once a prefix of the BIE has been + received. When this bit is set however, the BIE will + contain the higher layers before the lower layers. This + avoids additional buffer memory in the encoder and is + intended for applications where the encoder is connected + to a database which can easily reorder the SDEs before + sending them to a decoder. Warning: JBIG decoders are + not expected to support the HITOLO option (e.g. the + JBIG-KIT decoder does currently not) so you should + normally not use it. + + JBG_SEQ Usually, at first all stripes of one resolution layer + are written to the BIE and then all stripes of the next + layer, and so on. When the SEQ bit is set however, then + all layers of the first stripe will be written, + followed by all layers of the second stripe, etc. This + option also should normally never be required and is + not supported by the current JBIG-KIT decoder. + + JBG_SMID In case there exist several bit planes, then the order of + the stripes is determined by 3 loops over all stripes, + all planes and all layers. When SMID is set, the loop + over all stripes is the middle loop. + + JBG_ILEAVE If this bit is set, then at first all layers of one + plane are written before the encoder starts with the next + plane. + +The above description might be somewhat confusing, but the following +table (see also Table 11 in ITU-T T.82) makes clear how the three bits +JBG_SEQ, JBIG_ILEAVE and JBG_SMID influence the ordering of the loops +over all stripes, planes and layers: + + + Loops: + JBG_SEQ JBG_ILEAVE JBG_SMID | Outer Middle Inner + ------------------------------------+--------------------------- + 0 0 0 | p d s + 0 1 0 | d p s + 0 1 1 | d s p + 1 0 0 | s p d + 1 0 1 | p s d + 1 1 0 | s d p + + p: plane, s: stripe, d: layer + + +By default, the order combination JBG_ILEAVE | JBG_SMID is used. + +The options value can contain the following bits, which activate +some of the optional algorithms defined by JBIG: + + JBG_LRLTWO Normally, in the lowest resolution layer, pixels + from three lines around the next pixel are used + in order to determine the context in which the next + pixel is encoded. Some people in the JBIG committee + seem to have argued that using only 2 lines will + make software implementations a little bit faster, + however others have argued that using only two lines + will decrease compression efficiency by around 5%. + As you might expect from a committee, now both + alternatives are allowed and if JBG_LRLTWO is set, + the slightly faster but 5% less well compressing two + line alternative is selected. God bless the committees. + Although probably nobody will ever need this option, + it has been implemented in JBIG-KIT and is off by + default. + + JBG_TPDON This activates the "typical prediction" algorithm + for differential layers which avoids that large + areas of equal color have to be encoded at all. + This is on by default and there is no good reason to + switch it off except for debugging or preparing data + for cheap JBIG hardware which does not support this + option. + + JBG_TPBON Like JBG_TPDON this activates the "typical prediction" + algorithm in the lowest resolution layer. Also activated + by default. + + JBG_DPON This bit activates for the differential resolution + layers the "deterministic prediction" algorithm, + which avoids that higher resolution layer pixels are + encoded when their value can already be determined + with the knowledge of the neighbor pixels, the + corresponding lower resolution pixels and the + resolution reduction algorithm. This is also + activated by default and one only might perhaps want + to deactivate it if the default resolution reduction + algorithm is replaced by a new one. + + JBG_DELAY_AT Use a slightly less efficient algorithm to determine + when an adaptive template change is necessary. With + this bit set, the encoder output is compatible to the + conformance test examples in cause 7.2 of ITU-T T.82. + Then all adaptive template changes are delayed until + the first line of the next stripe. This option is by + default deactivated and only required for passing a + special compatibility test suite. + +In addition, parameter l0 in jbg_enc_options() allows you to specify +the number of lines per stripe in resolution layer 0. The parameters +mx and my change the maximal offset allowed for the adaptive template +pixel. The JBIG-KIT implementation allows currently a maximal mx value +of 23 in the encoder and 32 in the decoder. Parameter my is at the +moment ignored and always set to 0. As the standard requires of all +decoder implementations only a maximum supported mx = 16 and my = 0, +higher values should normally be avoided in order to guarantee +interoperability. Default is mx = 8 and my = 0. If any of the +parameters order, options, l0, mx or my is negative, then this value +is ignored and the current value stays unmodified. + +The resolution reduction and deterministic prediction tables can also +be replaced. However as these options are anyway only for experts, +please have a look at the source code of jbg_enc_out() and the struct +members dppriv and res_tab of struct jbg_enc_state for the details of +how to do this in case you really need it. The functions +jbg_int2dppriv and jbg_dppriv2int are provided in order to convert the +DPTABLE data from the format used in the standard into the more +efficient format used internally by JBIG-KIT. + +If you want to encode a greyscale image, you can use the library +function + + void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, + int encode_planes, + const unsigned char *src, unsigned char **dest, + int use_graycode); + +It separates an image in which each pixel is represented by one or +more bytes into separate bitplanes. The dest array of pointers to +these bitplanes can then be handed over to jbg_enc_init(). The +variables x and y specify the width and height of the image in pixels, +and has_planes specifies how many bits per pixel are used. As each +pixel is represented by an integral number of consecutive bytes, of +which each contains up to eight bits, the total length of the input +image array src[] will therefore be x * y * ((has_planes + 7) / 8) +bytes. The pixels are stored as usually in English reading order, and +for each pixel the integer value is stored with the most significant +byte coming first (Bigendian). This is exactly the format used in raw +PGM files. In encode_planes, the number of bitplanes that shall be +extracted can be specified. This allows for instance to extract only +the most significant 8 bits of a 12-bit image, where each pixel is +represented by two bytes, by specifying has_planes = 12 and +encode_planes = 8. If use_graycode is zero, then the binary code of +the pixel integer values will be used instead of the Gray code. Plane +0 contains always the most significant bit. + + +3 Decompressing an image + +Like with the compression functions, if you want to use the JBIG-KIT +library, you have to put the line + + #include "jbig.h" + +into your source code and link your executable with libjbig.a. + +The state of a JBIG decoder is stored completely in a struct and you +will have to define a variable like + + struct jbg_dec_state sd; + +which is initialized by a call to + + void jbg_dec_init(struct jbg_dec_state *s); + +After this, you can directly start to pass data from the BIE to the decoder +by calling the function + + int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, + size_t *cnt); + +The pointer data points to the first byte of a data block with length +len, which contains bytes from a BIE. It is not necessary to pass a +whole BIE at once to jbg_dec_in(), it can arrive fragmented in any way +by calling jbg_dec_in() several times. It is also possible to send +several BIEs concatenated to jbg_dec_in(), however these then have to +fit together. If you send several BIEs to the decoder, the lowest +resolution layer in each following BIE has to be the highest +resolution layer in the previous BIE plus one and the image sizes and +number of planes also have to fit together, otherwise jbg_dec_in() +will return the error JBG_ENOCONT after the header of the new BIE has +been received completely. + +If pointer cnt is not NULL, then the number of bytes actually read +from the data block is stored there. In case the data block did not +contain the end of the BIE, then the value JBG_EAGAIN will be returned +and *cnt equals len. + +Once the end of a BIE has been reached, the return value of +jbg_dec_in() will be JBG_EOK. After this has happened, the functions +and macros + + long jbg_dec_getwidth(struct jbg_dec_state *s); + long jbg_dec_getheight(struct jbg_dec_state *s); + int jbg_dec_getplanes(struct jbg_dec_state *s); + unsigned char *jbg_dec_getimage(struct jbg_dec_state *s, int plane); + long jbg_dec_getsize(struct jbg_dec_state *s); + +can be used to query the dimensions of the now completely decoded +image and to get a pointer to all bitmap planes. The bitmaps are +stored as described in section 2.1. The function jbg_dec_getsize() +calculates the number of bytes which one bitmap requires. + +The function + + void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, + void (*data_out)(unsigned char *start, size_t len, + void *file), void *file); + +allows you to merge the bitplanes that can be accessed individually +with jbg_dec_getimage() into an array with one or more bytes per pixel +(i.e., the format provided to jbg_split_planes()). If use_graycode is +zero, then a binary encoding will be used. The output array will be +delivered via the callback function data_out, exactly in the same way +in which the encoder provides the BIE. The function + + long jbg_dec_getsize_merged(const struct jbg_dec_state *s); + +determines how long the data array delivered by jbg_dec_merge_planes() +is going to be. + +Before calling jbg_dec_in() the first time, it is possible to specify with +a call to + + void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax, + unsigned long ymax); + +an abort criterion for progressively encoded images. For instance if an +application will display a whole document on a screen which is 1024 x +768 pixels large, then this application should call + + jbg_dec_maxsize(&sd, 1024, 768); + +before the decoding process starts. If the image has been encoded in +progressive mode (i.e. with several resolution layers), then the +decoder will stop with a return value JBG_EOK_INTR after the largest +resolution layer that is still smaller than 1024 x 768. However this +is no guarantee that the image which can then be read out using +jbg_dec_getimage(), etc. is really not larger than the specified +maximal size. The application will have to check the size of the +image, because the decoder does not automatically apply a resolution +reduction if no suitable resolution layer is available in the BIE. + +If jbg_dec_in() returned JBG_EOK_INTR or JBG_EOK, then it is possible +to continue calling jbg_dec_in() with the remaining data in order to +either decode the remaining resolution layers of the current BIE or in +order to add another BIE with additional resolution layers. In both +cases, after jbg_dec_in() returned JBG_EOK_INTR or JBG_EOK, *cnt is +probably not equal to len and the remainder of the data block which +has not yet been processed by the decoder has to be delivered to +jbg_dec_in() again. + +If any other return value than JBG_EOK, JBG_EOK_INTR or JBG_EAGAIN +has been returned by jbg_dec_in(), then an error has occurred and + + void jbg_dec_free(struct jbg_dec_state *s); + +should be called in order to release any allocated memory. The +destructor jbg_dec_free() should of course also be called, once the +decoded bitmap returned by jbg_dec_getimage() is no longer required +and the memory can be released. + +The function + + const char *jbg_strerror(int errnum, int language); + +returns a pointer to a short single line test message which explains +the return value of jbg_dec_in(). This message can be used in order to +provide the user a brief informative message about what when wrong +while decompressing the JBIG image. The error messages are available +in several languages and in several character sets. Currently +supported are the following values for the language parameter: + + JBG_EN English messages in ASCII + JBG_DE_8859_1 German messages in ISO 8859-1 Latin 1 character set + JBG_DE_UTF_8 German messages in ISO 10646/Unicode UTF-8 encoding + + +The current implementation of the JBIG-KIT decoder has the following +limitations: + + - The maximal horizontal offset mx of the adaptive template pixel + must not be larger than 32 and the maximal vertical offset must + be zero. + + - HITOLO and SEQ bits must not be set in the order value. + +A more detailed description of the JBIG-KIT implementation is + + Markus Kuhn: Effiziente Kompression von bi-level Bilddaten durch + kontextsensitive arithmetische Codierung. Studienarbeit, Lehrstuhl + für Betriebssysteme, IMMD IV, Universität Erlangen-Nürnberg, + Erlangen, July 1995. (German, 62 pages) + + +Please quote the above if you use JBIG-KIT in your research project. + +*** Happy compressing *** + +[end] diff --git a/converter/other/jbig/jbig.h b/converter/other/jbig/jbig.h new file mode 100644 index 00000000..dd9a76f3 --- /dev/null +++ b/converter/other/jbig/jbig.h @@ -0,0 +1,267 @@ +/* + * Header file for the portable free JBIG compression library + * + * Markus Kuhn -- mkuhn@acm.org + * + * $Id: jbig.h,v 1.9 1999-11-16 15:58:45+00 mgk25 Rel $ + */ + +#ifndef JBG_H +#define JBG_H + +#include + +/* + * JBIG-KIT version number + */ + +#define JBG_VERSION "1.1" + +/* + * Buffer block for SDEs which are temporarily stored by encoder + */ + +#define JBG_BUFSIZE 4000 + +struct jbg_buf { + unsigned char d[JBG_BUFSIZE]; /* one block of a buffer list */ + int len; /* length of the data in this block */ + struct jbg_buf *next; /* pointer to next block */ + struct jbg_buf *previous; /* pointer to previous block * + * (unused in freelist) */ + struct jbg_buf *last; /* only used in list head: final block of list */ + struct jbg_buf **free_list; /* pointer to pointer to head of free list */ +}; + +/* + * Maximum number of allowed ATMOVEs per stripe + */ + +#define JBG_ATMOVES_MAX 64 + +/* + * Option and order flags + */ + +#define JBG_HITOLO 0x08 +#define JBG_SEQ 0x04 +#define JBG_ILEAVE 0x02 +#define JBG_SMID 0x01 + +#define JBG_LRLTWO 0x40 +#define JBG_VLENGTH 0x20 +#define JBG_TPDON 0x10 +#define JBG_TPBON 0x08 +#define JBG_DPON 0x04 +#define JBG_DPPRIV 0x02 +#define JBG_DPLAST 0x01 + +#define JBG_DELAY_AT 0x100 /* delay ATMOVE until the first line of the next + * stripe. Option available for compatibility + * with conformance test example in clause 7.2.*/ + + +/* + * Possible error code return values + */ + +#define JBG_EOK 0 +#define JBG_EOK_INTR 1 +#define JBG_EAGAIN 2 +#define JBG_ENOMEM 3 +#define JBG_EABORT 4 +#define JBG_EMARKER 5 +#define JBG_ENOCONT 6 +#define JBG_EINVAL 7 +#define JBG_EIMPL 8 + +/* + * Language code for error message strings (based on ISO 639 2-letter + * standard language name abbreviations). + */ + +#define JBG_EN 0 /* English */ +#define JBG_DE_8859_1 1 /* German in ISO Latin 1 character set */ +#define JBG_DE_UTF_8 2 /* German in Unicode UTF-8 encoding */ + +/* + * Status description of an arithmetic encoder + */ + +struct jbg_arenc_state { + unsigned char st[4096]; /* probability status for contexts, MSB = MPS */ + unsigned long c; /* C register, base of coding intervall, * + * layout as in Table 23 */ + unsigned long a; /* A register, normalized size of coding intervall */ + long sc; /* counter for buffered 0xff values which might overflow */ + int ct; /* bit shift counter, determines when next byte will be written */ + int buffer; /* buffer for most recent output byte != 0xff */ + void (*byte_out)(int, void *); /* function which receives all PSCD bytes */ + void *file; /* parameter passed to byte_out */ +}; + + +/* + * Status description of an arithmetic decoder + */ + +struct jbg_ardec_state { + unsigned char st[4096]; /* probability status for contexts, MSB = MPS */ + unsigned long c; /* C register, base of coding intervall, * + * layout as in Table 25 */ + unsigned long a; /* A register, normalized size of coding intervall */ + int ct; /* bit shift counter, determines when next byte will be read */ + unsigned char *pscd_ptr; /* pointer to next PSCD data byte */ + unsigned char *pscd_end; /* pointer to byte after PSCD */ + enum { + JBG_OK, /* symbol has been successfully decoded */ + JBG_READY, /* no more bytes of this PSCD required, marker * + * encountered, probably more symbols available */ + JBG_MORE, /* more PSCD data bytes required to decode a symbol */ + JBG_MARKER /* more PSCD data bytes required, ignored final 0xff byte */ + } result; /* result of previous decode call */ + int startup; /* controls initial fill of s->c */ +}; + +#ifdef TEST_CODEC +void arith_encode_init(struct jbg_arenc_state *s, int reuse_st); +void arith_encode_flush(struct jbg_arenc_state *s); +void arith_encode(struct jbg_arenc_state *s, int cx, int pix); +void arith_decode_init(struct jbg_ardec_state *s, int reuse_st); +int arith_decode(struct jbg_ardec_state *s, int cx); +#endif + + +/* + * Status of a JBIG encoder + */ + +struct jbg_enc_state { + int d; /* resolution layer of the input image */ + unsigned long xd, yd; /* size of the input image (resolution layer d) */ + int planes; /* number of different bitmap planes */ + int dl; /* lowest resolution layer in the next BIE */ + int dh; /* highest resolution layer in the next BIE */ + unsigned long l0; /* number of lines per stripe at lowest * + * resolution layer 0 */ + unsigned long stripes; /* number of stripes required (determ. by l0) */ + unsigned char **lhp[2]; /* pointers to lower/higher resolution images */ + int *highres; /* index [plane] of highres image in lhp[] */ + int order; /* SDE ordering parameters */ + int options; /* encoding parameters */ + unsigned mx, my; /* maximum ATMOVE window size */ + int *tx; /* array [plane] with x-offset of adaptive template pixel */ + char *dppriv; /* optional private deterministic prediction table */ + char *res_tab; /* table for the resolution reduction algorithm */ + struct jbg_buf ****sde; /* array [stripe][layer][plane] pointers to * + * buffers for stored SDEs */ + struct jbg_arenc_state *s; /* array [planes] for arithm. encoder status */ + struct jbg_buf *free_list; /* list of currently unused SDE block buffers */ + void (*data_out)(unsigned char *start, size_t len, void *file); + /* data write callback */ + void *file; /* parameter passed to data_out() */ + char *tp; /* buffer for temp. values used by diff. typical prediction */ +}; + + +/* + * Status of a JBIG decoder + */ + +struct jbg_dec_state { + /* data from BIH */ + int d; /* resolution layer of the full image */ + int dl; /* first resolution layer in this BIE */ + unsigned long xd, yd; /* size of the full image (resolution layer d) */ + int planes; /* number of different bitmap planes */ + unsigned long l0; /* number of lines per stripe at lowest * + * resolution layer 0 */ + unsigned long stripes; /* number of stripes required (determ. by l0) */ + int order; /* SDE ordering parameters */ + int options; /* encoding parameters */ + int mx, my; /* maximum ATMOVE window size */ + char *dppriv; /* optional private deterministic prediction table */ + + /* loop variables */ + unsigned long ii[3]; /* current stripe, layer, plane (outer loop first) */ + + /* + * Pointers to array [planes] of lower/higher resolution images. + * lhp[d & 1] contains image of layer d. + */ + unsigned char **lhp[2]; + + /* status information */ + int **tx, **ty; /* array [plane][layer-dl] with x,y-offset of AT pixel */ + struct jbg_ardec_state **s; /* array [plane][layer-dl] for arithmetic * + * decoder status */ + int **reset; /* array [plane][layer-dl] remembers if previous stripe * + * in that plane/resolution ended with SDRST. */ + unsigned long bie_len; /* number of bytes read so far */ + unsigned char buffer[20]; /* used to store BIH or marker segments fragm. */ + int buf_len; /* number of bytes in buffer */ + unsigned long comment_skip; /* remaining bytes of a COMMENT segment */ + unsigned long x; /* x position of next pixel in current SDE */ + unsigned long i; /* line in current SDE (first line of each stripe is 0) */ + int at_moves; /* number of AT moves in the current stripe */ + unsigned long at_line[JBG_ATMOVES_MAX]; /* lines at which an * + * AT move will happen */ + int at_tx[JBG_ATMOVES_MAX], at_ty[JBG_ATMOVES_MAX]; /* ATMOVE offsets in * + * current stripe */ + unsigned long line_h1, line_h2, line_h3; /* variables of decode_pscd */ + unsigned long line_l1, line_l2, line_l3; + int pseudo; /* flag for TPBON/TPDON: next pixel is pseudo pixel */ + int **lntp; /* flag [plane][layer-dl] for TP: line is not typical */ + + unsigned long xmax, ymax; /* if possible abort before image gets * + * larger than this size */ + int dmax; /* abort after this layer */ +}; + + +/* some macros (too trivial for a function) */ + +#define jbg_dec_getplanes(s) ((s)->planes) + + +/* function prototypes */ + +void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, + int planes, unsigned char **p, + void (*data_out)(unsigned char *start, size_t len, + void *file), + void *file); +int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth, + unsigned long mheight); +void jbg_enc_layers(struct jbg_enc_state *s, int d); +int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh); +void jbg_enc_options(struct jbg_enc_state *s, int order, int options, + long l0, int mx, int my); +void jbg_enc_out(struct jbg_enc_state *s); +void jbg_enc_free(struct jbg_enc_state *s); + +void jbg_dec_init(struct jbg_dec_state *s); +void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax, + unsigned long ymax); +int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, + size_t *cnt); +long jbg_dec_getwidth(const struct jbg_dec_state *s); +long jbg_dec_getheight(const struct jbg_dec_state *s); +unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane); +long jbg_dec_getsize(const struct jbg_dec_state *s); +void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, + void (*data_out)(unsigned char *start, size_t len, + void *file), void *file); +long jbg_dec_getsize_merged(const struct jbg_dec_state *s); +void jbg_dec_free(struct jbg_dec_state *s); + +const char *jbg_strerror(int errnum, int language); +void jbg_int2dppriv(unsigned char *dptable, const char *internal); +void jbg_dppriv2int(char *internal, const unsigned char *dptable); +unsigned long jbg_ceil_half(unsigned long x, int n); +void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, + int encode_planes, + const unsigned char *src, unsigned char **dest, + int use_graycode); + +#endif /* JBG_H */ diff --git a/converter/other/jbig/jbig_tab.c b/converter/other/jbig/jbig_tab.c new file mode 100644 index 00000000..55183503 --- /dev/null +++ b/converter/other/jbig/jbig_tab.c @@ -0,0 +1,428 @@ +/* + * 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 new file mode 100644 index 00000000..7a6e95c1 --- /dev/null +++ b/converter/other/jbig/jbigtopnm.c @@ -0,0 +1,286 @@ +/* + jbigtopnm - JBIG to PNM converter + + This program was derived from jbgtopbm.c in Markus Kuhn's + JBIG-KIT package by Bryan Henderson on 2000.05.11 + + The main difference is that this version uses the Netpbm libraries. + + */ + +#include +#include +#include +#include +#include "pnm.h" + +#define BUFSIZE 8192 + + +static void +collect_image (unsigned char *data, size_t len, void *image) { + static int cursor = 0; + int i; + + for (i = 0; i < len; i++) { + ((unsigned char *)image)[cursor++] = data[i]; + } +} + + + +static void +write_pnm (FILE *fout, const unsigned char * const image, const int bpp, + const int rows, const int cols, const int maxval, + const int format) { + + int row; + xel *pnm_row; + + pnm_writepnminit(fout, cols, rows, maxval, format, 0); + + pnm_row = pnm_allocrow(cols); + + for (row = 0; row < rows; row++) { + int col; + for (col = 0; col < cols; col++) { + int j; + for (j = 0; j < bpp; j++) + PNM_ASSIGN1(pnm_row[col], + image[(((row*cols)+col) * bpp) + j]); + } + pnm_writepnmrow(fout, pnm_row, cols, maxval, format, 0); + } + + pnm_freerow(pnm_row); +} + + + +static void +write_raw_pbm(FILE * const fout, + const unsigned char * const binary_image, + int const cols, + int const rows) { + + unsigned int const bytes_per_row = pbm_packed_bytes(cols); + + int row; + + pbm_writepbminit(fout, cols, rows, 0); + + for (row = 0; row < rows; ++row) + pbm_writepbmrow_packed(fout, &binary_image[row*bytes_per_row], cols, + 0); +} + + + +/* + * + */ +static void +diagnose_bie(FILE *f) +{ + unsigned char bih[20]; + int len; + unsigned long xd, yd, l0; + + len = fread(bih, 1, 20, f); + if (len < 20) { + printf("Input file is %d < 20 bytes long and does therefore not " + "contain an intact BIE header!\n", len); + return; + } + + printf("Decomposition of BIH:\n\n DL = %d\n D = %d\n P = %d\n" + " - = %d\n XD = %lu\n YD = %lu\n L0 = %lu\n MX = %d\n" + " MY = %d\n", + bih[0], bih[1], bih[2], bih[3], + xd = ((unsigned long) bih[ 4] << 24) | ((unsigned long)bih[ 5] << 16)| + ((unsigned long) bih[ 6] << 8) | ((unsigned long) bih[ 7]), + yd = ((unsigned long) bih[ 8] << 24) | ((unsigned long)bih[ 9] << 16)| + ((unsigned long) bih[10] << 8) | ((unsigned long) bih[11]), + l0 = ((unsigned long) bih[12] << 24) | ((unsigned long)bih[13] << 16)| + ((unsigned long) bih[14] << 8) | ((unsigned long) bih[15]), + bih[16], bih[17]); + printf(" order = %d %s%s%s%s%s\n", bih[18], + bih[18] & JBG_HITOLO ? " HITOLO" : "", + bih[18] & JBG_SEQ ? " SEQ" : "", + bih[18] & JBG_ILEAVE ? " ILEAVE" : "", + bih[18] & JBG_SMID ? " SMID" : "", + bih[18] & 0xf0 ? " other" : ""); + printf(" options = %d %s%s%s%s%s%s%s%s\n", bih[19], + bih[19] & JBG_LRLTWO ? " LRLTWO" : "", + bih[19] & JBG_VLENGTH ? " VLENGTH" : "", + bih[19] & JBG_TPDON ? " TPDON" : "", + bih[19] & JBG_TPBON ? " TPBON" : "", + bih[19] & JBG_DPON ? " DPON" : "", + bih[19] & JBG_DPPRIV ? " DPPRIV" : "", + bih[19] & JBG_DPLAST ? " DPLAST" : "", + bih[19] & 0x80 ? " other" : ""); + printf("\n %lu stripes, %d layers, %d planes\n\n", + ((yd >> bih[1]) + ((((1UL << bih[1]) - 1) & xd) != 0) + l0 - 1) / l0, + bih[1] - bih[0], bih[2]); + + return; +} + + +int main (int argc, char **argv) +{ + FILE *fin = stdin, *fout = stdout; + const char *fnin = "", *fnout = ""; + int i, j, result; + int all_args = 0, files = 0; + struct jbg_dec_state s; + char *buffer; + unsigned char *p; + size_t len, cnt; + unsigned long xmax = 4294967295UL, ymax = 4294967295UL; + int plane = -1, use_graycode = 1, diagnose = 0; + + pnm_init(&argc, argv); + + buffer = malloc(BUFSIZE); + if (!buffer) + pm_error("Sorry, not enough memory available!"); + + /* parse command line arguments */ + for (i = 1; i < argc; i++) { + if (!all_args && argv[i][0] == '-') { + if (argv[i][1] == '\0' && files == 0) + ++files; + else { + for (j = 1; j > 0 && argv[i][j]; j++) { + switch(tolower(argv[i][j])) { + case '-' : + all_args = 1; + break; + case 'b': + use_graycode = 0; + break; + case 'd': + diagnose = 1; + break; + case 'x': + if (++i >= argc) + pm_error("-x needs a value"); + xmax = atol(argv[i]); + j = -1; + break; + case 'y': + if (++i >= argc) + pm_error("-y needs a value"); + ymax = atol(argv[i]); + j = -1; + break; + case 'p': + if (++i >= argc) + pm_error("-p needs a value"); + plane = atoi(argv[i]); + j = -1; + break; + default: + pm_error("Unrecognized option: %c", argv[i][j]); + } + } + } + } else { + switch (files++) { + case 0: + if (argv[i][0] != '-' || argv[i][1] != '\0') { + fnin = argv[i]; + fin = fopen(fnin, "rb"); + if (!fin) + pm_error("Can't open input file '%s'", fnin); + } + if (diagnose) { + diagnose_bie(fin); + exit(0); + } + break; + case 1: + fnout = argv[i]; + fout = fopen(fnout, "wb"); + if (!fout) + pm_error("Can't open output file '%s'", fnout); + break; + default: + pm_error("Too many non-option arguments"); + } + } + } + + /* send input file to decoder */ + jbg_dec_init(&s); + jbg_dec_maxsize(&s, xmax, ymax); + result = JBG_EAGAIN; + do { + len = fread(buffer, 1, BUFSIZE, fin); + if (!len) break; + cnt = 0; + p = (unsigned char *) buffer; + while (len > 0 && (result == JBG_EAGAIN || result == JBG_EOK)) { + result = jbg_dec_in(&s, p, len, &cnt); + p += cnt; + len -= cnt; + } + } while (result == JBG_EAGAIN || result == JBG_EOK); + if (ferror(fin)) + 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)); + if (plane >= 0 && jbg_dec_getplanes(&s) <= plane) + pm_error("Image has only %d planes!\n", jbg_dec_getplanes(&s)); + + { + /* Write it out */ + + int rows, cols; + int maxval; + int bpp; + int plane_to_write; + + cols = jbg_dec_getwidth(&s); + rows = jbg_dec_getheight(&s); + maxval = pm_bitstomaxval(jbg_dec_getplanes(&s)); + bpp = (jbg_dec_getplanes(&s)+7)/8; + + if (jbg_dec_getplanes(&s) == 1) + plane_to_write = 0; + else + plane_to_write = plane; + + if (plane_to_write >= 0) { + /* Write just one plane */ + unsigned char * binary_image; + + pm_message("WRITING PBM FILE"); + + binary_image=jbg_dec_getimage(&s, plane_to_write); + write_raw_pbm(fout, binary_image, cols, rows); + } else { + unsigned char *image; + pm_message("WRITING PGM FILE"); + + /* Write out all the planes */ + /* What jbig.doc doesn't tell you is that jbg_dec_merge_planes + delivers the image in chunks, in consecutive calls to + the data-out callback function. And a row can span two + chunks. + */ + image = malloc(cols*rows*bpp); + jbg_dec_merge_planes(&s, use_graycode, collect_image, image); + write_pnm(fout, image, bpp, rows, cols, maxval, PGM_TYPE); + free(image); + } + } + + pm_close(fout); + + jbg_dec_free(&s); + + return 0; +} diff --git a/converter/other/jbig/pnmtojbig.c b/converter/other/jbig/pnmtojbig.c new file mode 100644 index 00000000..9dbef3fa --- /dev/null +++ b/converter/other/jbig/pnmtojbig.c @@ -0,0 +1,463 @@ +/* + pnmtojbig - PNM to JBIG converter + + This program was derived from pbmtojbg.c in Markus Kuhn's + JBIG-KIT package by Bryan Henderson on 2000.05.11 + + The main difference is that this version uses the Netpbm libraries. + + */ + +/* + The JBIG standard doesn't say which end of the scale is white and + which end is black in a BIE. It has a recommendation in terms of + foreground and background (a concept which does not exist in the + Netpbm formats) for single-plane images, and is silent for + multi-plane images. + + Kuhn's implementation of the JBIG standard says if the BIE has a + single plane, then in that plane a zero bit means white and a one + bit means black. But if it has multiple planes, a composite zero + value means black and a composite maximal value means white. + + Actually, Kuhn's pbmtojbg doesn't even implement this, but rather + bases the distinction on whether the input file was PBM or PGM. + This means that if you convert a PGM file with maxval 1 to a JBIG + file and then back, the result (which is a PBM file) is the + inverse of what you started with. Same if the PGM file has + maxval > 1 but you use a -t option to write only one plane. We + assume this is just a bug in pbmtojpg and that hardly anybody does + this. So we adopt the implementation described above. + + This means that after jbg_split_planes() hands us a set of bitmap + planes, if there is only one of them, we have to invert all the + bits in it. + +*/ + +#include +#include +#include +#include + +#include "pm_c_util.h" +#include "mallocvar.h" +#include "pnm.h" + +static unsigned long total_length = 0; + /* used for determining output file length */ + +/* + * malloc() with exception handler + */ +static void +*checkedmalloc(size_t n) +{ + void *p; + + if ((p = malloc(n)) == NULL) { + fprintf(stderr, "Sorry, not enough memory available!\n"); + exit(1); + } + + return p; +} + + +/* + * Callback procedure which is used by JBIG encoder to deliver the + * encoded data. It simply sends the bytes to the output file. + */ +static void data_out(unsigned char *start, size_t len, void *file) +{ + fwrite(start, len, 1, (FILE *) file); + total_length += len; + return; +} + + + +static void +readPbm(FILE * const fin, + unsigned int const cols, + unsigned int const rows, + unsigned char *** const bitmapP) { + + unsigned int const bytes_per_line = pbm_packed_bytes(cols); + + unsigned char ** bitmap; + + /* Read the input image into bitmap[] */ + /* Shortcut for PBM */ + int row; + bitmap = (unsigned char **) checkedmalloc(sizeof(unsigned char *)); + bitmap[0] = (unsigned char *) checkedmalloc(bytes_per_line * rows); + + for (row = 0; row < rows; row++) + pbm_readpbmrow_packed(fin, &bitmap[0][row*bytes_per_line], + cols, RPBM_FORMAT); + + *bitmapP = bitmap; +} + + + +static void +readImage(FILE * const fin, + unsigned int const cols, + unsigned int const rows, + xelval const maxval, + int const format, + unsigned int const bpp, + unsigned char ** const imageP) { +/*---------------------------------------------------------------------------- + Read the input image and put it into *imageP; + + Although the PBM case is separated, this logic works also for + PBM, bpp=1. +-----------------------------------------------------------------------------*/ + unsigned char *image; + /* This is a representation of the entire image with 'bpp' bytes per + pixel. The 'bpp' bytes for each pixel are arranged MSB first + and its numerical value is the value from the PNM input. + The pixels are laid out in row-major format in this rectangle. + + The point of this data structure is it is what jbg_split_planes() + wants for input. + */ + xel* pnm_row; + unsigned int row; + + pnm_row = pnm_allocrow(cols); /* row buffer */ + MALLOCARRAY_NOFAIL(image, cols * rows * bpp); + + for (row = 0; row < rows; ++row) { + unsigned int col; + pnm_readpnmrow(fin, pnm_row, cols, maxval, format); + for (col = 0; col < cols; col++) { + unsigned int j; + /* Move each byte of the sample into image[], MSB first */ + for (j = 0; j < bpp; ++j) + image[(((row*cols)+col) * bpp) + j] = (unsigned char) + PNM_GET1(pnm_row[col]) >> ((bpp-1-j) * 8); + } + } + pnm_freerow(pnm_row); + *imageP = image; +} + + + +static void +convertImageToBitmap(unsigned char * const image, + unsigned char *** const bitmapP, + unsigned int const encode_planes, + unsigned int const bytes_per_line, + unsigned int const lines) { + + /* Convert image[] into bitmap[] */ + + unsigned char ** bitmap; + unsigned int i; + + MALLOCARRAY_NOFAIL(bitmap, encode_planes); + for (i = 0; i < encode_planes; ++i) + MALLOCARRAY_NOFAIL(bitmap[i], bytes_per_line * lines); + + *bitmapP = bitmap; +} + + + +static void +readPnm(FILE * const fin, + unsigned int const cols, + unsigned int const rows, + xelval const maxval, + int const format, + unsigned int const bpp, + unsigned int const planes, + unsigned int const encode_planes, + bool const use_graycode, + unsigned char *** const bitmapP) { + + unsigned int const bytes_per_line = pbm_packed_bytes(cols); + + unsigned char * image; + unsigned char ** bitmap; + + readImage(fin, cols, rows, maxval, format, bpp, &image); + + convertImageToBitmap(image, &bitmap, encode_planes, bytes_per_line, rows); + + jbg_split_planes(cols, rows, planes, encode_planes, image, bitmap, + use_graycode); + free(image); + + /* Invert the image if it is just one plane. See top of this file + for an explanation why. Due to the separate handling of PBM, + this is for exceptional PGM files. + */ + + if (encode_planes == 1) { + unsigned int row; + for (row = 0; row < rows; ++row) { + unsigned int i; + for (i = 0; i < bytes_per_line; i++) + bitmap[0][(row*bytes_per_line) + i] ^= 0xff; + + if (cols % 8 > 0) { + bitmap[0][ (row+1)*bytes_per_line -1] >>= 8-cols%8; + bitmap[0][ (row+1)*bytes_per_line -1] <<= 8-cols%8; + } + } + } + *bitmapP = bitmap; +} + + + +int +main(int argc, char **argv) { + FILE *fin = stdin, *fout = stdout; + const char *fnin = "", *fnout = ""; + int i; + int all_args = 0, files = 0; + int bpp, planes, encode_planes = -1; + int cols, rows; + xelval maxval; + int format; + unsigned char **bitmap; + /* This is an array of the planes of the image. Each plane is a + two-dimensional array of pixels laid out in row-major format. + format with each pixel being one bit. A byte in the array + contains 8 pixels left to right, msb to lsb. + */ + + struct jbg_enc_state s; + int verbose = 0, delay_at = 0, use_graycode = 1; + long mwidth = 640, mheight = 480; + int dl = -1, dh = -1, d = -1, l0 = -1, mx = -1; + int options = JBG_TPDON | JBG_TPBON | JBG_DPON; + int order = JBG_ILEAVE | JBG_SMID; + + pbm_init(&argc, argv); + + /* parse command line arguments */ + for (i = 1; i < argc; ++i) { + int j; + if (!all_args && argv[i][0] == '-') { + if (argv[i][1] == '\0' && files == 0) + ++files; + else { + for (j = 1; j > 0 && argv[i][j]; j++) { + switch(tolower(argv[i][j])) { + case '-' : + all_args = 1; + break; + case 'v': + verbose = 1; + break; + case 'b': + use_graycode = 0; + break; + case 'c': + delay_at = 1; + break; + case 'x': + if (++i >= argc) + pm_error("-x needs a value"); + j = -1; + mwidth = atol(argv[i]); + break; + case 'y': + if (++i >= argc) + pm_error("-y needsa value"); + j = -1; + mheight = atol(argv[i]); + break; + case 'o': + if (++i >= argc) + pm_error("-o needs a value"); + j = -1; + order = atoi(argv[i]); + break; + case 'p': + if (++i >= argc) + pm_error("-p needs a value"); + j = -1; + options = atoi(argv[i]); + break; + case 'l': + if (++i >= argc) + pm_error("-l needs a value"); + j = -1; + dl = atoi(argv[i]); + break; + case 'h': + if (++i >= argc) + pm_error("-h needs a value"); + j = -1; + dh = atoi(argv[i]); + break; + case 'q': + d = 0; + break; + case 'd': + if (++i >= argc) + pm_error("-d needs a value"); + j = -1; + d = atoi(argv[i]); + break; + case 's': + if (++i >= argc) + pm_error("-s needs a value"); + j = -1; + l0 = atoi(argv[i]); + break; + case 't': + if (++i >= argc) + pm_error("-t needs a value"); + j = -1; + encode_planes = atoi(argv[i]); + break; + case 'm': + if (++i >= argc) + pm_error("-m needs a value"); + j = -1; + mx = atoi(argv[i]); + break; + default: + pm_error("Unrecognized option: %c", argv[i][j]); + } + } + } + } else { + switch (files++) { + case 0: + if (argv[i][0] != '-' || argv[i][1] != '\0') { + fnin = argv[i]; + fin = fopen(fnin, "rb"); + if (!fin) { + fprintf(stderr, "Can't open input file '%s", fnin); + perror("'"); + exit(1); + } + } + break; + case 1: + fnout = argv[i]; + fout = fopen(fnout, "wb"); + if (!fout) { + fprintf(stderr, "Can't open input file '%s", fnout); + perror("'"); + exit(1); + } + break; + default: + pm_error("too many non-option arguments"); + } + } + } + + pnm_readpnminit(fin, &cols, &rows, &maxval, &format); + + if (PNM_FORMAT_TYPE(format) != PGM_TYPE && + PNM_FORMAT_TYPE(format) != PBM_TYPE) + pm_error("This program accepts PBM and PGM input only. " + "Try Ppmtopgm."); + + planes = pm_maxvaltobits(maxval); + + /* In a JBIG file, maxvals are determined only by the number of planes, + so must be a power of 2 minus 1 + */ + + if ((1UL << planes)-1 != maxval) + pm_error("Input image has unacceptable maxval: %d. JBIG files must " + "have a maxval which is a power of 2 minus 1. Use " + "Ppmdepth to adjust the image's maxval", maxval); + + bpp = (planes + 7) / 8; + + if (encode_planes < 0 || encode_planes > planes) + encode_planes = planes; + + if (bpp == 1 && PNM_FORMAT_TYPE(format) == PBM_TYPE) + readPbm(fin, cols, rows, &bitmap); + else + readPnm(fin, cols, rows, maxval, format, bpp, + planes, encode_planes, use_graycode, + &bitmap); + + /* Apply JBIG algorithm and write BIE to output file */ + + /* initialize parameter struct for JBIG encoder*/ + jbg_enc_init(&s, cols, rows, encode_planes, bitmap, data_out, fout); + + /* Select number of resolution layers either directly or based + * on a given maximum size for the lowest resolution layer */ + if (d >= 0) + jbg_enc_layers(&s, d); + else + jbg_enc_lrlmax(&s, mwidth, mheight); + + /* Specify a few other options (each is ignored if negative) */ + if (delay_at) + options |= JBG_DELAY_AT; + jbg_enc_lrange(&s, dl, dh); + jbg_enc_options(&s, order, options, l0, mx, -1); + + /* now encode everything and send it to data_out() */ + jbg_enc_out(&s); + + /* give encoder a chance to free its temporary data structures */ + jbg_enc_free(&s); + + /* check for file errors and close fout */ + if (ferror(fout) || fclose(fout)) { + fprintf(stderr, "Problem while writing output file '%s", fnout); + perror("'"); + exit(1); + } + + /* In case the user wants to know all the gory details ... */ + if (verbose) { + fprintf(stderr, "Information about the created JBIG bi-level image entity " + "(BIE):\n\n"); + fprintf(stderr, " input image size: %ld x %ld pixel\n", + s.xd, s.yd); + fprintf(stderr, " bit planes: %d\n", s.planes); + if (s.planes > 1) + fprintf(stderr, " encoding: %s code, MSB first\n", + use_graycode ? "Gray" : "binary"); + fprintf(stderr, " stripes: %ld\n", s.stripes); + fprintf(stderr, " lines per stripe in layer 0: %ld\n", s.l0); + fprintf(stderr, " total number of diff. layers: %d\n", s.d); + fprintf(stderr, " lowest layer in BIE: %d\n", s.dl); + fprintf(stderr, " highest layer in BIE: %d\n", s.dh); + fprintf(stderr, " lowest layer size: %lu x %lu pixel\n", + jbg_ceil_half(s.xd, s.d - s.dl), jbg_ceil_half(s.yd, s.d - s.dl)); + fprintf(stderr, " highest layer size: %lu x %lu pixel\n", + jbg_ceil_half(s.xd, s.d - s.dh), jbg_ceil_half(s.yd, s.d - s.dh)); + fprintf(stderr, " option bits:%s%s%s%s%s%s%s\n", + s.options & JBG_LRLTWO ? " LRLTWO" : "", + s.options & JBG_VLENGTH ? " VLENGTH" : "", + s.options & JBG_TPDON ? " TPDON" : "", + s.options & JBG_TPBON ? " TPBON" : "", + s.options & JBG_DPON ? " DPON" : "", + s.options & JBG_DPPRIV ? " DPPRIV" : "", + s.options & JBG_DPLAST ? " DPLAST" : ""); + fprintf(stderr, " order bits:%s%s%s%s\n", + s.order & JBG_HITOLO ? " HITOLO" : "", + s.order & JBG_SEQ ? " SEQ" : "", + s.order & JBG_ILEAVE ? " ILEAVE" : "", + s.order & JBG_SMID ? " SMID" : ""); + fprintf(stderr, " AT maximum x-offset: %d\n" + " AT maximum y-offset: %d\n", s.mx, s.my); + fprintf(stderr, " length of output file: %lu byte\n\n", + total_length); + } + + return 0; +} -- cgit 1.4.1