📄 configured_jbig.c
字号:
/* * Portable Free JBIG image compression library * * Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ * * $Id: jbig.c,v 1.22 2004-06-11 15:17:06+01 mgk25 Exp $ * * This module implements a portable standard C encoder and decoder * using the JBIG lossless bi-level image compression algorithm as * specified in International Standard ISO 11544:1993 or equivalently * as specified in ITU-T Recommendation T.82. See the file jbig.doc * for usage instructions and application examples. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * If you want to use this program under different license conditions, * then contact the author for an arrangement. * * It is possible that certain products which can be built using this * software module might form inventions protected by patent rights in * some countries (e.g., by patents about arithmetic coding algorithms * owned by IBM and AT&T in the USA). Provision of this software by the * author does NOT include any licences for any patents. In those * countries where a patent licence is required for certain applications * of this software module, you will have to obtain such a licence * yourself. */#ifdef DEBUG#include <stdio.h>#else#define NDEBUG#endif#include <stdlib.h>#include <string.h>#include <assert.h>#include <stdio.h>#include "configured_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 127 /* 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//extern void arith_encode(unsigned cx, unsigned pix, unsigned long *pCount);/* 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.22 2004-06-11 15:17:06+01 mgk25 Exp $ ";#define WRITE_BYTE(byte, s) (s)->sde[(s)->sde_index++] = (unsigned char)(byte);/* * 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. * In contrast to C's malloc() and realloc(), but like C's calloc(), * these functions take two parameters nmemb and size that are multiplied * before being passed on to the corresponding C function. * This we can catch all overflows during a size_t multiplication a * a single place. */#ifndef SIZE_MAX#define SIZE_MAX ((size_t) -1) /* largest value of size_t */#endifstatic void *checked_malloc(size_t nmemb, size_t size){ void *p; /* Full manual exception handling is ugly here for performance * reasons. If an adequate handling of lack of memory is required, * then use C++ and throw a C++ exception instead of abort(). */ /* assert that nmemb * size <= SIZE_MAX */ if (size > SIZE_MAX / nmemb) abort(); p = malloc(nmemb * size); if (!p) abort();#if 0 fprintf(stderr, "%p = malloc(%lu * %lu)\n", p, (unsigned long) nmemb, (unsigned long) size);#endif return p;}static void *checked_realloc(void *ptr, size_t nmemb, size_t size){ void *p; /* Full manual exception handling is ugly here for performance * reasons. If an adequate handling of lack of memory is required, * then use C++ and throw a C++ exception here instead of abort(). */ /* assert that nmemb * size <= SIZE_MAX */ if (size > SIZE_MAX / nmemb) abort(); p = realloc(ptr, nmemb * size); if (!p) abort();#if 0 fprintf(stderr, "%p = realloc(%p, %lu * %lu)\n", p, ptr, (unsigned long) nmemb, (unsigned long) size);#endif return p;}static void checked_free(void *ptr){ free(ptr);#if 0 fprintf(stderr, "free(%p)\n", ptr);#endif}#pragma optimize_for_speedstatic void WriteBufString(struct jbg_enc_state* s, unsigned char* head, unsigned size){ unsigned i; for(i=0; i<size; i++) s->sde[s->sde_index++] = head[i];}/* * 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 DEBUGstatic long encoded_pixels = 0;#endifARITH void arith_encode_init(struct jbg_arenc_state *s, int reuse_st){ int i; if (!reuse_st) for (i = 0; i < 1024; s->st[i++] = 0); s->c = 0; s->a = 0x10000UL; // Normalized size of coding intervall is 65536. @chenyi.srf s->sc = 0; s->ct = 11; s->buffer = -1; /* empty */ s->s = NULL; return;}#pragma optimize_for_speedARITH 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) { WRITE_BYTE(s->buffer + 1, s->s); if (s->buffer + 1 == MARKER_ESC) WRITE_BYTE(MARKER_STUFF, s->s); } /* output 0x00 bytes only when more non-0x00 will follow */ if (s->c & 0x7fff800L) for (; s->sc; --s->sc) WRITE_BYTE(0x00, s->s); } else { if (s->buffer >= 0) WRITE_BYTE(s->buffer, s->s); /* T.82 figure 30 says buffer+1 for the above line! Typo? */ for (; s->sc; --s->sc) { WRITE_BYTE(0xff, s->s); WRITE_BYTE(MARKER_STUFF, s->s); } } /* output final bytes only if they are not 0x00 */ if (s->c & 0x7fff800L) { WRITE_BYTE((s->c >> 19) & 0xff, s->s); if (((s->c >> 19) & 0xff) == MARKER_ESC) WRITE_BYTE(MARKER_STUFF, s->s); if (s->c & 0x7f800L) { WRITE_BYTE((s->c >> 11) & 0xff, s->s); if (((s->c >> 11) & 0xff) == MARKER_ESC) WRITE_BYTE(MARKER_STUFF, s->s); } } return;}// @chenyi.srf// Parameters:// cx: CX register, a label identifying an arithmetic coding context.// pix: current pixelstatic void arith_encode(struct jbg_arenc_state *s, int cx, int pix) { extern short jbg_lsz[]; // Probability estimation tables @chenyi.srf extern unsigned char jbg_nmps[], jbg_nlps[]; // See jbig_tab.c @chenyi.srf register unsigned lsz, ss; register unsigned char *st; long temp;#ifdef DEBUG ++encoded_pixels;#endif assert(cx >= 0 && cx < 4096); st = s->st + cx; // cx will be the index of st table ss = *st & 0x7f; assert(ss < 113); lsz = jbg_lsz[ss]; 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; WRITE_BYTE(s->buffer, s->s); if (s->buffer == MARKER_ESC) WRITE_BYTE(MARKER_STUFF, s->s); } for (; s->sc; --s->sc) WRITE_BYTE(0x00, s->s); 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) WRITE_BYTE(s->buffer, s->s); for (; s->sc; --s->sc) { WRITE_BYTE(0xff, s->s); WRITE_BYTE(MARKER_STUFF, s->s); } 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 < 1024; 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;}/* * Remove any trailing zero bytes from the end of a linked jbg_buf list,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -