/contrib/sdk/sources/libjbig2dec/Makefile |
---|
0,0 → 1,18 |
CC = kos32-gcc |
LD = kos32-ld |
SDK_DIR = /media/maxim/E22406D62406AE1B/SVNKOS/contrib/sdk |
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 |
INCLUDES = -I $(SDK_DIR)/sources/newlib/libc/include -I $(SDK_DIR)/sources/freetype/include -I $(SDK_DIR)/sources/libpng -I $(SDK_DIR)/sources/zlib -I . |
SRC := $(notdir $(wildcard *.c)) |
OBJECTS = $(patsubst %.c, %.o, $(SRC)) |
default: $(patsubst %.c,%.o,$(SRC)) |
ar rcs libjbig2dec.a *.o |
rm *.o |
mv libjbig2dec.a ../../lib |
%.o : %.c Makefile $(SRC) |
$(CC) $(CFLAGS) -DHAVE_CONFIG_H $(INCLUDES) -o $@ $< |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/Tupfile.lua |
---|
0,0 → 1,10 |
if tup.getconfig("NO_GCC") ~= "" then return end |
HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../../../programs" or tup.getconfig("HELPERDIR") |
tup.include(HELPERDIR .. "/use_gcc.lua") |
tup.include(HELPERDIR .. "/use_newlib.lua") |
CFLAGS = CFLAGS .. " -std=c99 -DHAVE_CONFIG_H" |
INCLUDES = INCLUDES .. " -I ." |
compile_gcc{"jbig2_arith.c", "jbig2_arith_iaid.c", "jbig2_arith_int.c", "jbig2.c", "jbig2dec.c", "jbig2_generic.c", "jbig2_halftone.c", "jbig2_huffman.c", "jbig2_image.c", "jbig2_image_pbm.c", "jbig2_metadata.c", "jbig2_mmr.c", "jbig2_page.c", "jbig2_refinement.c", "jbig2_segment.c", "jbig2_symbol_dict.c", "jbig2_text.c", "memcmp.c", "sha1.c"} |
tup.rule(OBJS, "kos32-ar rcs %o %f", {"../../lib/libjbig2dec.a", "<../../lib/libjbig2dec>"}) |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/config.h |
---|
0,0 → 1,120 |
/* config.h. Generated from config.h.in by configure. */ |
/* config.h.in. Generated from configure.ac by autoheader. */ |
/* Define if building universal (internal helper macro) */ |
/* #undef AC_APPLE_UNIVERSAL_BUILD */ |
/* Define to 1 if you have the <dlfcn.h> header file. */ |
#define HAVE_DLFCN_H 1 |
/* Define if the local libc includes getopt_long() */ |
#define HAVE_GETOPT_LONG /**/ |
/* Define to 1 if you have the <inttypes.h> header file. */ |
#define HAVE_INTTYPES_H 1 |
/* Define to 1 if you have the <libintl.h> header file. */ |
#define HAVE_LIBINTL_H 1 |
/* Define if libpng is available (-lpng) */ |
#define HAVE_LIBPNG 1 |
/* Define to 1 if you have the <memory.h> header file. */ |
#define HAVE_MEMORY_H 1 |
/* Define to 1 if you have the `memset' function. */ |
#define HAVE_MEMSET 1 |
/* Define to 1 if you have the `snprintf' function. */ |
#define HAVE_SNPRINTF 1 |
/* Define to 1 if you have the <stddef.h> header file. */ |
#define HAVE_STDDEF_H 1 |
/* Define to 1 if you have the <stdint.h> header file. */ |
#define HAVE_STDINT_H 1 |
/* Define to 1 if you have the <stdlib.h> header file. */ |
#define HAVE_STDLIB_H 1 |
/* Define to 1 if you have the `strdup' function. */ |
#define HAVE_STRDUP 1 |
/* Define to 1 if you have the <strings.h> header file. */ |
#define HAVE_STRINGS_H 1 |
/* Define to 1 if you have the <string.h> header file. */ |
#define HAVE_STRING_H 1 |
/* Define to 1 if you have the <sys/stat.h> header file. */ |
#define HAVE_SYS_STAT_H 1 |
/* Define to 1 if you have the <sys/types.h> header file. */ |
#define HAVE_SYS_TYPES_H 1 |
/* Define to 1 if you have the <unistd.h> header file. */ |
#define HAVE_UNISTD_H 1 |
/* set by configure if an alternate header with the stdint.h types is found */ |
/* #undef JBIG2_REPLACE_STDINT_H */ |
/* Define to the sub-directory in which libtool stores uninstalled libraries. |
*/ |
#define LT_OBJDIR ".libs/" |
/* Define to 1 if your C compiler doesn't accept -c and -o together. */ |
/* #undef NO_MINUS_C_MINUS_O */ |
/* Name of package */ |
#define PACKAGE "jbig2dec" |
/* Define to the address where bug reports for this package should be sent. */ |
#define PACKAGE_BUGREPORT "jbig2-dev@ghostscript.com" |
/* Define to the full name of this package. */ |
#define PACKAGE_NAME "jbig2dec" |
/* Define to the full name and version of this package. */ |
#define PACKAGE_STRING "jbig2dec 0.11" |
/* Define to the one symbol short name of this package. */ |
#define PACKAGE_TARNAME "jbig2dec" |
/* Define to the version of this package. */ |
#define PACKAGE_VERSION "0.11" |
/* The size of `char', as computed by sizeof. */ |
#define SIZEOF_CHAR 1 |
/* The size of `int', as computed by sizeof. */ |
#define SIZEOF_INT 4 |
/* The size of `long', as computed by sizeof. */ |
#define SIZEOF_LONG 4 |
/* The size of `short', as computed by sizeof. */ |
#define SIZEOF_SHORT 2 |
/* Define to 1 if you have the ANSI C header files. */ |
#define STDC_HEADERS 1 |
/* Version number of package */ |
#define VERSION "0.11" |
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most |
significant byte first (like Motorola and SPARC, unlike Intel). */ |
#if defined AC_APPLE_UNIVERSAL_BUILD |
# if defined __BIG_ENDIAN__ |
# define WORDS_BIGENDIAN 1 |
# endif |
#else |
# ifndef WORDS_BIGENDIAN |
/* # undef WORDS_BIGENDIAN */ |
# endif |
#endif |
/* Define to empty if `const' does not conform to ANSI C. */ |
/* #undef const */ |
/* Define to `unsigned int' if <sys/types.h> does not define. */ |
/* #undef size_t */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/config_types.h |
---|
0,0 → 1,19 |
/* |
generated header with missing types for the |
jbig2dec program and library. include this |
after config.h, within the HAVE_CONFIG_H |
ifdef |
*/ |
#ifndef HAVE_STDINT_H |
# ifdef JBIG2_REPLACE_STDINT_H |
# include <no_replacement_found> |
# else |
typedef unsigned int uint32_t; |
typedef unsigned short uint16_t; |
typedef unsigned char uint8_t; |
typedef signed int int32_t; |
typedef signed short int16_t; |
typedef signed char int8_t; |
# endif /* JBIG2_REPLACE_STDINT */ |
#endif /* HAVE_STDINT_H */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/config_win32.h |
---|
0,0 → 1,41 |
/* |
jbig2dec |
Copyright (C) 2002-2003 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* configuration header file for compiling under Microsoft Windows */ |
/* update package version here */ |
#define PACKAGE "jbig2dec" |
#define VERSION "0.3" |
#if defined(_MSC_VER) || (defined(__BORLANDC__) && defined(__WIN32__)) |
/* Microsoft Visual C++ or Borland C++ */ |
typedef signed char int8_t; |
typedef short int int16_t; |
typedef int int32_t; |
typedef __int64 int64_t; |
typedef unsigned char uint8_t; |
typedef unsigned short int uint16_t; |
typedef unsigned int uint32_t; |
/* no uint64_t */ |
# if defined(_MSC_VER) |
# if _MSC_VER < 1500 /* VS 2008 has vsnprintf */ |
# define vsnprintf _vsnprintf |
# endif |
# endif |
# define snprintf _snprintf |
#endif /* _MSC_VER */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/getopt.h |
---|
0,0 → 1,180 |
/* Declarations for getopt. |
Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
02111-1307 USA. */ |
#ifndef _GETOPT_H |
#ifndef __need_getopt |
# define _GETOPT_H 1 |
#endif |
/* If __GNU_LIBRARY__ is not already defined, either we are being used |
standalone, or this is the first header included in the source file. |
If we are being used with glibc, we need to include <features.h>, but |
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is |
not defined, include <ctype.h>, which will pull in <features.h> for us |
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it |
doesn't flood the namespace with stuff the way some other headers do.) */ |
#if !defined __GNU_LIBRARY__ |
# include <ctype.h> |
#endif |
#ifdef __cplusplus |
extern "C" { |
#endif |
/* For communication from `getopt' to the caller. |
When `getopt' finds an option that takes an argument, |
the argument value is returned here. |
Also, when `ordering' is RETURN_IN_ORDER, |
each non-option ARGV-element is returned here. */ |
extern char *optarg; |
/* Index in ARGV of the next element to be scanned. |
This is used for communication to and from the caller |
and for communication between successive calls to `getopt'. |
On entry to `getopt', zero means this is the first call; initialize. |
When `getopt' returns -1, this is the index of the first of the |
non-option elements that the caller should itself scan. |
Otherwise, `optind' communicates from one call to the next |
how much of ARGV has been scanned so far. */ |
extern int optind; |
/* Callers store zero here to inhibit the error message `getopt' prints |
for unrecognized options. */ |
extern int opterr; |
/* Set to an option character which was unrecognized. */ |
extern int optopt; |
#ifndef __need_getopt |
/* Describe the long-named options requested by the application. |
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector |
of `struct option' terminated by an element containing a name which is |
zero. |
The field `has_arg' is: |
no_argument (or 0) if the option does not take an argument, |
required_argument (or 1) if the option requires an argument, |
optional_argument (or 2) if the option takes an optional argument. |
If the field `flag' is not NULL, it points to a variable that is set |
to the value given in the field `val' when the option is found, but |
left unchanged if the option is not found. |
To have a long-named option do something other than set an `int' to |
a compiled-in constant, such as set a value from `optarg', set the |
option's `flag' field to zero and its `val' field to a nonzero |
value (the equivalent single-letter option character, if there is |
one). For long options that have a zero `flag' field, `getopt' |
returns the contents of the `val' field. */ |
struct option |
{ |
# if (defined __STDC__ && __STDC__) || defined __cplusplus |
const char *name; |
# else |
char *name; |
# endif |
/* has_arg can't be an enum because some compilers complain about |
type mismatches in all the code that assumes it is an int. */ |
int has_arg; |
int *flag; |
int val; |
}; |
/* Names for the values of the `has_arg' field of `struct option'. */ |
# define no_argument 0 |
# define required_argument 1 |
# define optional_argument 2 |
#endif /* need getopt */ |
/* Get definitions and prototypes for functions to process the |
arguments in ARGV (ARGC of them, minus the program name) for |
options given in OPTS. |
Return the option character from OPTS just read. Return -1 when |
there are no more options. For unrecognized options, or options |
missing arguments, `optopt' is set to the option letter, and '?' is |
returned. |
The OPTS string is a list of characters which are recognized option |
letters, optionally followed by colons, specifying that that letter |
takes an argument, to be placed in `optarg'. |
If a letter in OPTS is followed by two colons, its argument is |
optional. This behavior is specific to the GNU `getopt'. |
The argument `--' causes premature termination of argument |
scanning, explicitly telling `getopt' that there are no more |
options. |
If OPTS begins with `--', then non-option arguments are treated as |
arguments to the option '\0'. This behavior is specific to the GNU |
`getopt'. */ |
#if (defined __STDC__ && __STDC__) || defined __cplusplus |
# ifdef __GNU_LIBRARY__ |
/* Many other libraries have conflicting prototypes for getopt, with |
differences in the consts, in stdlib.h. To avoid compilation |
errors, only prototype getopt for the GNU C library. */ |
extern int getopt (int __argc, char *const *__argv, const char *__shortopts); |
# else /* not __GNU_LIBRARY__ */ |
extern int getopt (); |
# endif /* __GNU_LIBRARY__ */ |
# ifndef __need_getopt |
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, |
const struct option *__longopts, int *__longind); |
extern int getopt_long_only (int __argc, char *const *__argv, |
const char *__shortopts, |
const struct option *__longopts, int *__longind); |
/* Internal only. Users should not call this directly. */ |
extern int _getopt_internal (int __argc, char *const *__argv, |
const char *__shortopts, |
const struct option *__longopts, int *__longind, |
int __long_only); |
# endif |
#else /* not __STDC__ */ |
extern int getopt (); |
# ifndef __need_getopt |
extern int getopt_long (); |
extern int getopt_long_only (); |
extern int _getopt_internal (); |
# endif |
#endif /* __STDC__ */ |
#ifdef __cplusplus |
} |
#endif |
/* Make sure we later can get all the definitions and declarations. */ |
#undef __need_getopt |
#endif /* getopt.h */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2.c |
---|
0,0 → 1,428 |
/* |
jbig2dec |
Copyright (C) 2002-2005 Artifex Software, Inc. |
This software is provided AS-IS with no warranty, |
either express or implied. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdarg.h> |
#include <string.h> |
#include "jbig2.h" |
#include "jbig2_priv.h" |
static void * |
jbig2_default_alloc (Jbig2Allocator *allocator, size_t size) |
{ |
return malloc (size); |
} |
static void |
jbig2_default_free (Jbig2Allocator *allocator, void *p) |
{ |
free (p); |
} |
static void * |
jbig2_default_realloc (Jbig2Allocator *allocator, void *p, size_t size) |
{ |
return realloc (p, size); |
} |
static Jbig2Allocator jbig2_default_allocator = |
{ |
jbig2_default_alloc, |
jbig2_default_free, |
jbig2_default_realloc |
}; |
void * |
jbig2_alloc (Jbig2Allocator *allocator, size_t size) |
{ |
return allocator->alloc (allocator, size); |
} |
void |
jbig2_free (Jbig2Allocator *allocator, void *p) |
{ |
allocator->free (allocator, p); |
} |
void * |
jbig2_realloc (Jbig2Allocator *allocator, void *p, size_t size) |
{ |
return allocator->realloc (allocator, p, size); |
} |
static int |
jbig2_default_error(void *data, const char *msg, |
Jbig2Severity severity, int32_t seg_idx) |
{ |
/* report only fatal errors by default */ |
if (severity == JBIG2_SEVERITY_FATAL) { |
fprintf(stderr, "jbig2 decoder FATAL ERROR: %s", msg); |
if (seg_idx != -1) fprintf(stderr, " (segment 0x%02x)", seg_idx); |
fprintf(stderr, "\n"); |
fflush(stderr); |
} |
return 0; |
} |
int |
jbig2_error(Jbig2Ctx *ctx, Jbig2Severity severity, int32_t segment_number, |
const char *fmt, ...) |
{ |
char buf[1024]; |
va_list ap; |
int n; |
int code; |
va_start (ap, fmt); |
n = vsnprintf (buf, sizeof(buf), fmt, ap); |
va_end (ap); |
if (n < 0 || n == sizeof(buf)) |
strncpy (buf, "jbig2_error: error in generating error string", sizeof(buf)); |
code = ctx->error_callback (ctx->error_callback_data, buf, severity, segment_number); |
if (severity == JBIG2_SEVERITY_FATAL) |
code = -1; |
return code; |
} |
Jbig2Ctx * |
jbig2_ctx_new (Jbig2Allocator *allocator, |
Jbig2Options options, |
Jbig2GlobalCtx *global_ctx, |
Jbig2ErrorCallback error_callback, |
void *error_callback_data) |
{ |
Jbig2Ctx *result; |
if (allocator == NULL) |
allocator = &jbig2_default_allocator; |
if (error_callback == NULL) |
error_callback = &jbig2_default_error; |
result = (Jbig2Ctx *)jbig2_alloc(allocator, sizeof(Jbig2Ctx)); |
if (result == NULL) { |
error_callback(error_callback_data, "initial context allocation failed!", |
JBIG2_SEVERITY_FATAL, -1); |
return result; |
} |
result->allocator = allocator; |
result->options = options; |
result->global_ctx = (const Jbig2Ctx *)global_ctx; |
result->error_callback = error_callback; |
result->error_callback_data = error_callback_data; |
result->state = (options & JBIG2_OPTIONS_EMBEDDED) ? |
JBIG2_FILE_SEQUENTIAL_HEADER : |
JBIG2_FILE_HEADER; |
result->buf = NULL; |
result->n_segments = 0; |
result->n_segments_max = 16; |
result->segments = (Jbig2Segment **)jbig2_alloc(allocator, result->n_segments_max * sizeof(Jbig2Segment *)); |
result->segment_index = 0; |
result->current_page = 0; |
result->max_page_index = 4; |
result->pages = (Jbig2Page *)jbig2_alloc(allocator, result->max_page_index * sizeof(Jbig2Page)); |
{ |
int index; |
for (index = 0; index < result->max_page_index; index++) { |
result->pages[index].state = JBIG2_PAGE_FREE; |
result->pages[index].number = 0; |
result->pages[index].image = NULL; |
} |
} |
return result; |
} |
int32_t |
jbig2_get_int32 (const byte *buf) |
{ |
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; |
} |
int16_t |
jbig2_get_int16 (const byte *buf) |
{ |
return (buf[0] << 8) | buf[1]; |
} |
/** |
* jbig2_data_in: submit data for decoding |
* @ctx: The jbig2dec decoder context |
* @data: a pointer to the data buffer |
* @size: the size of the data buffer in bytes |
* |
* Copies the specified data into internal storage and attempts |
* to (continue to) parse it as part of a jbig2 data stream. |
* |
* Return code: 0 on success |
* -1 if there is a parsing error, or whatever |
* the error handling callback returns |
**/ |
int |
jbig2_data_in (Jbig2Ctx *ctx, const unsigned char *data, size_t size) |
{ |
const size_t initial_buf_size = 1024; |
if (ctx->buf == NULL) |
{ |
size_t buf_size = initial_buf_size; |
do |
buf_size <<= 1; |
while (buf_size < size); |
ctx->buf = (byte *)jbig2_alloc(ctx->allocator, buf_size); |
ctx->buf_size = buf_size; |
ctx->buf_rd_ix = 0; |
ctx->buf_wr_ix = 0; |
} |
else if (ctx->buf_wr_ix + size > ctx->buf_size) |
{ |
if (ctx->buf_rd_ix <= (ctx->buf_size >> 1) && |
ctx->buf_wr_ix - ctx->buf_rd_ix + size <= ctx->buf_size) |
{ |
memmove(ctx->buf, ctx->buf + ctx->buf_rd_ix, |
ctx->buf_wr_ix - ctx->buf_rd_ix); |
} |
else |
{ |
byte *buf; |
size_t buf_size = initial_buf_size; |
do |
buf_size <<= 1; |
while (buf_size < ctx->buf_wr_ix - ctx->buf_rd_ix + size); |
buf = (byte *)jbig2_alloc(ctx->allocator, buf_size); |
memcpy(buf, ctx->buf + ctx->buf_rd_ix, |
ctx->buf_wr_ix - ctx->buf_rd_ix); |
jbig2_free(ctx->allocator, ctx->buf); |
ctx->buf = buf; |
ctx->buf_size = buf_size; |
} |
ctx->buf_wr_ix -= ctx->buf_rd_ix; |
ctx->buf_rd_ix = 0; |
} |
memcpy(ctx->buf + ctx->buf_wr_ix, data, size); |
ctx->buf_wr_ix += size; |
/* data has now been added to buffer */ |
for (;;) |
{ |
const byte jbig2_id_string[8] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a }; |
Jbig2Segment *segment; |
size_t header_size; |
int code; |
switch (ctx->state) |
{ |
case JBIG2_FILE_HEADER: |
/* D.4.1 */ |
if (ctx->buf_wr_ix - ctx->buf_rd_ix < 9) |
return 0; |
if (memcmp(ctx->buf + ctx->buf_rd_ix, jbig2_id_string, 8)) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"Not a JBIG2 file header"); |
/* D.4.2 */ |
ctx->file_header_flags = ctx->buf[ctx->buf_rd_ix + 8]; |
if (ctx->file_header_flags & 0xFC) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, |
"reserved bits (2-7) of file header flags are not zero (0x%02x)", ctx->file_header_flags); |
} |
/* D.4.3 */ |
if (!(ctx->file_header_flags & 2)) /* number of pages is known */ |
{ |
if (ctx->buf_wr_ix - ctx->buf_rd_ix < 13) |
return 0; |
ctx->n_pages = jbig2_get_int32(ctx->buf + ctx->buf_rd_ix + 9); |
ctx->buf_rd_ix += 13; |
if (ctx->n_pages == 1) |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a single page document"); |
else |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a %d page document", ctx->n_pages); |
} |
else /* number of pages not known */ |
{ |
ctx->n_pages=0; |
ctx->buf_rd_ix += 9; |
} |
/* determine the file organization based on the flags - D.4.2 again */ |
if (ctx->file_header_flags & 1) |
{ |
ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates sequential organization"); |
} |
else |
{ |
ctx->state = JBIG2_FILE_RANDOM_HEADERS; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates random-access organization"); |
} |
break; |
case JBIG2_FILE_SEQUENTIAL_HEADER: |
case JBIG2_FILE_RANDOM_HEADERS: |
segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix, |
ctx->buf_wr_ix - ctx->buf_rd_ix, |
&header_size); |
if (segment == NULL) |
return 0; /* need more data */ |
ctx->buf_rd_ix += header_size; |
if (ctx->n_segments == ctx->n_segments_max) |
ctx->segments = (Jbig2Segment **)jbig2_realloc(ctx->allocator, |
ctx->segments, (ctx->n_segments_max <<= 2) * sizeof(Jbig2Segment *)); |
ctx->segments[ctx->n_segments++] = segment; |
if (ctx->state == JBIG2_FILE_RANDOM_HEADERS) |
{ |
if ((segment->flags & 63) == 51) /* end of file */ |
ctx->state = JBIG2_FILE_RANDOM_BODIES; |
} |
else /* JBIG2_FILE_SEQUENTIAL_HEADER */ |
ctx->state = JBIG2_FILE_SEQUENTIAL_BODY; |
break; |
case JBIG2_FILE_SEQUENTIAL_BODY: |
case JBIG2_FILE_RANDOM_BODIES: |
segment = ctx->segments[ctx->segment_index]; |
if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix) |
return 0; /* need more data */ |
code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix); |
ctx->buf_rd_ix += segment->data_length; |
ctx->segment_index++; |
if (ctx->state == JBIG2_FILE_RANDOM_BODIES) |
{ |
if (ctx->segment_index == ctx->n_segments) |
ctx->state = JBIG2_FILE_EOF; |
} |
else /* JBIG2_FILE_SEQUENCIAL_BODY */ |
{ |
ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER; |
} |
if (code < 0) |
{ |
ctx->state = JBIG2_FILE_EOF; |
return code; |
} |
break; |
case JBIG2_FILE_EOF: |
if (ctx->buf_rd_ix == ctx->buf_wr_ix) |
return 0; |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, |
"Garbage beyond end of file"); |
} |
} |
return 0; |
} |
void |
jbig2_ctx_free (Jbig2Ctx *ctx) |
{ |
Jbig2Allocator *ca = ctx->allocator; |
int i; |
jbig2_free(ca, ctx->buf); |
if (ctx->segments != NULL) { |
for (i = 0; i < ctx->n_segments; i++) |
jbig2_free_segment(ctx, ctx->segments[i]); |
jbig2_free(ca, ctx->segments); |
} |
if (ctx->pages != NULL) { |
for (i = 0; i <= ctx->current_page; i++) |
if (ctx->pages[i].image != NULL) |
jbig2_image_release(ctx, ctx->pages[i].image); |
jbig2_free(ca, ctx->pages); |
} |
jbig2_free(ca, ctx); |
} |
Jbig2GlobalCtx *jbig2_make_global_ctx (Jbig2Ctx *ctx) |
{ |
return (Jbig2GlobalCtx *)ctx; |
} |
void jbig2_global_ctx_free(Jbig2GlobalCtx *global_ctx) |
{ |
jbig2_ctx_free((Jbig2Ctx *)global_ctx); |
} |
/* I'm not committed to keeping the word stream interface. It's handy |
when you think you may be streaming your input, but if you're not |
(as is currently the case), it just adds complexity. |
*/ |
typedef struct { |
Jbig2WordStream super; |
const byte *data; |
size_t size; |
} Jbig2WordStreamBuf; |
static uint32_t |
jbig2_word_stream_buf_get_next_word(Jbig2WordStream *self, int offset) |
{ |
Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *)self; |
const byte *data = z->data; |
uint32_t result; |
if (offset + 4 < z->size) |
result = (data[offset] << 24) | (data[offset + 1] << 16) | |
(data[offset + 2] << 8) | data[offset + 3]; |
else if (offset >= z->size) |
return 0; |
else |
{ |
int i; |
result = 0; |
for (i = 0; i < z->size - offset; i++) |
result |= data[offset + i] << ((3 - i) << 3); |
} |
return result; |
} |
Jbig2WordStream * |
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size) |
{ |
Jbig2WordStreamBuf *result = (Jbig2WordStreamBuf *)jbig2_alloc(ctx->allocator, sizeof(Jbig2WordStreamBuf)); |
result->super.get_next_word = jbig2_word_stream_buf_get_next_word; |
result->data = data; |
result->size = size; |
return &result->super; |
} |
void |
jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws) |
{ |
jbig2_free(ctx->allocator, ws); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2.h |
---|
0,0 → 1,135 |
/* |
jbig2dec |
Copyright (C) 2002-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef __cplusplus |
extern "C" { |
#endif |
#ifndef _JBIG2_H |
#define _JBIG2_H |
/* warning levels */ |
typedef enum { |
JBIG2_SEVERITY_DEBUG, |
JBIG2_SEVERITY_INFO, |
JBIG2_SEVERITY_WARNING, |
JBIG2_SEVERITY_FATAL |
} Jbig2Severity; |
typedef enum { |
JBIG2_OPTIONS_EMBEDDED = 1 |
} Jbig2Options; |
/* forward public structure declarations */ |
typedef struct _Jbig2Allocator Jbig2Allocator; |
typedef struct _Jbig2Ctx Jbig2Ctx; |
typedef struct _Jbig2GlobalCtx Jbig2GlobalCtx; |
typedef struct _Jbig2Segment Jbig2Segment; |
typedef struct _Jbig2Image Jbig2Image; |
/* private structures */ |
typedef struct _Jbig2Page Jbig2Page; |
typedef struct _Jbig2SymbolDictionary Jbig2SymbolDictionary; |
/* |
this is the general image structure used by the jbig2dec library |
images are 1 bpp, packed into rows a byte at a time. stride gives |
the byte offset to the next row, while width and height define |
the size of the image area in pixels. |
*/ |
struct _Jbig2Image { |
int width, height, stride; |
uint8_t *data; |
int refcount; |
}; |
Jbig2Image* jbig2_image_new(Jbig2Ctx *ctx, int width, int height); |
Jbig2Image* jbig2_image_clone(Jbig2Ctx *ctx, Jbig2Image *image); |
void jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image); |
void jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image); |
void jbig2_image_clear(Jbig2Ctx *ctx, Jbig2Image *image, int value); |
Jbig2Image *jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image, |
int width, int height); |
/* errors are returned from the library via a callback. If no callback |
is provided (a NULL argument is passed ot jbig2_ctx_new) a default |
handler is used which prints fatal errors to the stderr stream. */ |
/* error callback */ |
typedef int (*Jbig2ErrorCallback) (void *data, |
const char *msg, Jbig2Severity severity, |
int32_t seg_idx); |
/* memory allocation is likewise done via a set of callbacks so that |
clients can better control memory usage. If a NULL is passed for |
this argumennt of jbig2_ctx_new, a default allocator based on malloc() |
is used. */ |
/* dynamic memory callbacks */ |
struct _Jbig2Allocator { |
void *(*alloc) (Jbig2Allocator *allocator, size_t size); |
void (*free) (Jbig2Allocator *allocator, void *p); |
void *(*realloc) (Jbig2Allocator *allocator, void *p, size_t size); |
}; |
/* decoder context */ |
Jbig2Ctx *jbig2_ctx_new (Jbig2Allocator *allocator, |
Jbig2Options options, |
Jbig2GlobalCtx *global_ctx, |
Jbig2ErrorCallback error_callback, |
void *error_callback_data); |
void jbig2_ctx_free (Jbig2Ctx *ctx); |
/* global context for embedded streams */ |
Jbig2GlobalCtx *jbig2_make_global_ctx (Jbig2Ctx *ctx); |
void jbig2_global_ctx_free (Jbig2GlobalCtx *global_ctx); |
/* submit data to the decoder */ |
int jbig2_data_in (Jbig2Ctx *ctx, const unsigned char *data, size_t size); |
/* get the next available decoded page image. NULL means there isn't one. */ |
Jbig2Image *jbig2_page_out (Jbig2Ctx *ctx); |
/* mark a returned page image as no longer needed. */ |
int jbig2_release_page (Jbig2Ctx *ctx, Jbig2Image *image); |
/* mark the current page as complete, simulating an end-of-page segment (for broken streams) */ |
int jbig2_complete_page (Jbig2Ctx *ctx); |
/* segment header routines */ |
struct _Jbig2Segment { |
uint32_t number; |
uint8_t flags; |
uint32_t page_association; |
size_t data_length; |
int referred_to_segment_count; |
uint32_t *referred_to_segments; |
void *result; |
}; |
Jbig2Segment *jbig2_parse_segment_header (Jbig2Ctx *ctx, uint8_t *buf, size_t buf_size, |
size_t *p_header_size); |
int jbig2_parse_segment (Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data); |
void jbig2_free_segment (Jbig2Ctx *ctx, Jbig2Segment *segment); |
Jbig2Segment *jbig2_find_segment(Jbig2Ctx *ctx, uint32_t number); |
#endif /* _JBIG2_H */ |
#ifdef __cplusplus |
} |
#endif |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_arith.c |
---|
0,0 → 1,394 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is provided AS-IS with no warranty, |
either express or implied. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stdio.h> |
#include <stdlib.h> |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#ifdef JBIG2_DEBUG |
#include <stdio.h> |
#endif |
struct _Jbig2ArithState { |
uint32_t C; |
int A; |
int CT; |
uint32_t next_word; |
int next_word_bytes; |
Jbig2WordStream *ws; |
int offset; |
}; |
#undef SOFTWARE_CONVENTION |
/* |
A note on the "software conventions". |
Previously, I had misinterpreted the spec, and had thought that the |
spec's description of the "software convention" was wrong. Now I |
believe that this code is both correct and matches the spec, with |
SOFTWARE_CONVENTION defined or not. Thanks to William Rucklidge for |
the clarification. |
In any case, my benchmarking indicates no speed difference at all. |
Therefore, for now we will just use the normative version. |
*/ |
static void |
jbig2_arith_bytein (Jbig2ArithState *as) |
{ |
byte B; |
/* invariant: as->next_word_bytes > 0 */ |
/* Figure G.3 */ |
B = (byte)((as->next_word >> 24) & 0xFF); |
if (B == 0xFF) |
{ |
byte B1; |
if (as->next_word_bytes == 1) |
{ |
Jbig2WordStream *ws = as->ws; |
as->next_word = ws->get_next_word (ws, as->offset); |
as->offset += 4; |
B1 = (byte)((as->next_word >> 24) & 0xFF); |
if (B1 > 0x8F) |
{ |
#ifdef JBIG2_DEBUG_ARITH |
fprintf(stderr, "read %02x (aa)\n", B); |
#endif |
#ifndef SOFTWARE_CONVENTION |
as->C += 0xFF00; |
#endif |
as->CT = 8; |
as->next_word = (0xFF00 | B1) << 16; |
as->next_word_bytes = 2; |
} |
else |
{ |
#ifdef JBIG2_DEBUG_ARITH |
fprintf(stderr, "read %02x (a)\n", B); |
#endif |
#ifdef SOFTWARE_CONVENTION |
as->C += 0xFE00 - (B1 << 9); |
#else |
as->C += B1 << 9; |
#endif |
as->CT = 7; |
as->next_word_bytes = 4; |
} |
} |
else |
{ |
B1 = (byte)((as->next_word >> 16) & 0xFF); |
if (B1 > 0x8F) |
{ |
#ifdef JBIG2_DEBUG_ARITH |
fprintf(stderr, "read %02x (ba)\n", B); |
#endif |
#ifndef SOFTWARE_CONVENTION |
as->C += 0xFF00; |
#endif |
as->CT = 8; |
} |
else |
{ |
as->next_word_bytes--; |
as->next_word <<= 8; |
#ifdef JBIG2_DEBUG_ARITH |
fprintf(stderr, "read %02x (b)\n", B); |
#endif |
#ifdef SOFTWARE_CONVENTION |
as->C += 0xFE00 - (B1 << 9); |
#else |
as->C += (B1 << 9); |
#endif |
as->CT = 7; |
} |
} |
} |
else |
{ |
#ifdef JBIG2_DEBUG_ARITH |
fprintf(stderr, "read %02x\n", B); |
#endif |
as->CT = 8; |
as->next_word <<= 8; |
as->next_word_bytes--; |
if (as->next_word_bytes == 0) |
{ |
Jbig2WordStream *ws = as->ws; |
as->next_word = ws->get_next_word (ws, as->offset); |
as->offset += 4; |
as->next_word_bytes = 4; |
} |
B = (byte)((as->next_word >> 24) & 0xFF); |
#ifdef SOFTWARE_CONVENTION |
as->C += 0xFF00 - (B << 8); |
#else |
as->C += (B << 8); |
#endif |
} |
} |
#if defined(JBIG2_DEBUG) || defined(JBIG2_DEBUG_ARITH) |
#include <stdio.h> |
static void |
jbig2_arith_trace (Jbig2ArithState *as, Jbig2ArithCx cx) |
{ |
fprintf(stderr, "I = %2d, MPS = %d, A = %04x, CT = %2d, C = %08x\n", |
cx & 0x7f, cx >> 7, as->A, as->CT, as->C); |
} |
#endif |
/** Allocate and initialize a new arithmetic coding state |
* the returned pointer can simply be freed; this does |
* not affect the associated Jbig2WordStream. |
*/ |
Jbig2ArithState * |
jbig2_arith_new (Jbig2Ctx *ctx, Jbig2WordStream *ws) |
{ |
Jbig2ArithState *result; |
result = (Jbig2ArithState *)jbig2_alloc(ctx->allocator, |
sizeof(Jbig2ArithState)); |
result->ws = ws; |
result->next_word = ws->get_next_word (ws, 0); |
result->next_word_bytes = 4; |
result->offset = 4; |
/* Figure G.1 */ |
#ifdef SOFTWARE_CONVENTION |
result->C = (~(result->next_word >> 8)) & 0xFF0000; |
#else |
result->C = (result->next_word >> 8) & 0xFF0000; |
#endif |
jbig2_arith_bytein (result); |
result->C <<= 7; |
result->CT -= 7; |
result->A = 0x8000; |
return result; |
} |
/* could put bit fields in to minimize memory usage */ |
typedef struct { |
unsigned short Qe; |
byte mps_xor; /* mps_xor = index ^ NMPS */ |
byte lps_xor; /* lps_xor = index ^ NLPS ^ (SWITCH << 7) */ |
} Jbig2ArithQe; |
const Jbig2ArithQe jbig2_arith_Qe[] = { |
{ 0x5601, 1 ^ 0, 1 ^ 0 ^ 0x80 }, |
{ 0x3401, 2 ^ 1, 6 ^ 1 }, |
{ 0x1801, 3 ^ 2, 9 ^ 2 }, |
{ 0x0AC1, 4 ^ 3, 12 ^ 3 }, |
{ 0x0521, 5 ^ 4, 29 ^ 4 }, |
{ 0x0221, 38 ^ 5, 33 ^ 5 }, |
{ 0x5601, 7 ^ 6, 6 ^ 6 ^ 0x80 }, |
{ 0x5401, 8 ^ 7, 14 ^ 7 }, |
{ 0x4801, 9 ^ 8, 14 ^ 8 }, |
{ 0x3801, 10 ^ 9, 14 ^ 9 }, |
{ 0x3001, 11 ^ 10, 17 ^ 10 }, |
{ 0x2401, 12 ^ 11, 18 ^ 11 }, |
{ 0x1C01, 13 ^ 12, 20 ^ 12 }, |
{ 0x1601, 29 ^ 13, 21 ^ 13 }, |
{ 0x5601, 15 ^ 14, 14 ^ 14 ^ 0x80 }, |
{ 0x5401, 16 ^ 15, 14 ^ 15 }, |
{ 0x5101, 17 ^ 16, 15 ^ 16 }, |
{ 0x4801, 18 ^ 17, 16 ^ 17 }, |
{ 0x3801, 19 ^ 18, 17 ^ 18 }, |
{ 0x3401, 20 ^ 19, 18 ^ 19 }, |
{ 0x3001, 21 ^ 20, 19 ^ 20 }, |
{ 0x2801, 22 ^ 21, 19 ^ 21 }, |
{ 0x2401, 23 ^ 22, 20 ^ 22 }, |
{ 0x2201, 24 ^ 23, 21 ^ 23 }, |
{ 0x1C01, 25 ^ 24, 22 ^ 24 }, |
{ 0x1801, 26 ^ 25, 23 ^ 25 }, |
{ 0x1601, 27 ^ 26, 24 ^ 26 }, |
{ 0x1401, 28 ^ 27, 25 ^ 27 }, |
{ 0x1201, 29 ^ 28, 26 ^ 28 }, |
{ 0x1101, 30 ^ 29, 27 ^ 29 }, |
{ 0x0AC1, 31 ^ 30, 28 ^ 30 }, |
{ 0x09C1, 32 ^ 31, 29 ^ 31 }, |
{ 0x08A1, 33 ^ 32, 30 ^ 32 }, |
{ 0x0521, 34 ^ 33, 31 ^ 33 }, |
{ 0x0441, 35 ^ 34, 32 ^ 34 }, |
{ 0x02A1, 36 ^ 35, 33 ^ 35 }, |
{ 0x0221, 37 ^ 36, 34 ^ 36 }, |
{ 0x0141, 38 ^ 37, 35 ^ 37 }, |
{ 0x0111, 39 ^ 38, 36 ^ 38 }, |
{ 0x0085, 40 ^ 39, 37 ^ 39 }, |
{ 0x0049, 41 ^ 40, 38 ^ 40 }, |
{ 0x0025, 42 ^ 41, 39 ^ 41 }, |
{ 0x0015, 43 ^ 42, 40 ^ 42 }, |
{ 0x0009, 44 ^ 43, 41 ^ 43 }, |
{ 0x0005, 45 ^ 44, 42 ^ 44 }, |
{ 0x0001, 45 ^ 45, 43 ^ 45 }, |
{ 0x5601, 46 ^ 46, 46 ^ 46 } |
}; |
static void |
jbig2_arith_renormd (Jbig2ArithState *as) |
{ |
/* Figure E.18 */ |
do |
{ |
if (as->CT == 0) |
jbig2_arith_bytein (as); |
as->A <<= 1; |
as->C <<= 1; |
as->CT--; |
} |
while ((as->A & 0x8000) == 0); |
} |
bool |
jbig2_arith_decode (Jbig2ArithState *as, Jbig2ArithCx *pcx) |
{ |
Jbig2ArithCx cx = *pcx; |
const Jbig2ArithQe *pqe = &jbig2_arith_Qe[cx & 0x7f]; |
bool D; |
/* Figure G.2 */ |
as->A -= pqe->Qe; |
if ( |
#ifdef SOFTWARE_CONVENTION |
/* Note: I do not think this is correct. See above. */ |
(as->C >> 16) < as->A |
#else |
!((as->C >> 16) < pqe->Qe) |
#endif |
) |
{ |
#ifndef SOFTWARE_CONVENTION |
as->C -= pqe->Qe << 16; |
#endif |
if ((as->A & 0x8000) == 0) |
{ |
/* MPS_EXCHANGE, Figure E.16 */ |
if (as->A < pqe->Qe) |
{ |
D = 1 - (cx >> 7); |
*pcx ^= pqe->lps_xor; |
} |
else |
{ |
D = cx >> 7; |
*pcx ^= pqe->mps_xor; |
} |
jbig2_arith_renormd (as); |
return D; |
} |
else |
return cx >> 7; |
} |
else |
{ |
#ifdef SOFTWARE_CONVENTION |
as->C -= (as->A) << 16; |
#endif |
/* LPS_EXCHANGE, Figure E.17 */ |
if (as->A < pqe->Qe) |
{ |
as->A = pqe->Qe; |
D = cx >> 7; |
*pcx ^= pqe->mps_xor; |
} |
else |
{ |
as->A = pqe->Qe; |
D = 1 - (cx >> 7); |
*pcx ^= pqe->lps_xor; |
} |
jbig2_arith_renormd (as); |
return D; |
} |
} |
#ifdef TEST |
static uint32_t |
test_get_word (Jbig2WordStream *self, int offset) |
{ |
byte stream[] = { |
0x84, 0xC7, 0x3B, 0xFC, 0xE1, 0xA1, 0x43, 0x04, 0x02, 0x20, 0x00, 0x00, |
0x41, 0x0D, 0xBB, 0x86, 0xF4, 0x31, 0x7F, 0xFF, 0x88, 0xFF, 0x37, 0x47, |
0x1A, 0xDB, 0x6A, 0xDF, 0xFF, 0xAC, |
0x00, 0x00 |
}; |
if (offset >= sizeof(stream)) |
return 0; |
else |
return (stream[offset] << 24) | (stream[offset + 1] << 16) | |
(stream[offset + 2] << 8) | stream[offset + 3]; |
} |
int |
main (int argc, char **argv) |
{ |
Jbig2Ctx *ctx; |
Jbig2WordStream ws; |
Jbig2ArithState *as; |
int i; |
Jbig2ArithCx cx = 0; |
ctx = jbig2_ctx_new(NULL, 0, NULL, NULL, NULL); |
ws.get_next_word = test_get_word; |
as = jbig2_arith_new (ctx, &ws); |
#ifdef JBIG2_DEBUG_ARITH |
jbig2_arith_trace (as, cx); |
#endif |
for (i = 0; i < 256; i++) |
{ |
bool D; |
D = jbig2_arith_decode (as, &cx); |
#ifdef JBIG2_DEBUG_ARITH |
fprintf(stderr, "%3d: D = %d, ", i, D); |
jbig2_arith_trace (as, cx); |
#endif |
} |
jbig2_free(ctx->allocator, as); |
jbig2_ctx_free(ctx); |
return 0; |
} |
#endif |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_arith.h |
---|
0,0 → 1,31 |
/* |
jbig2dec |
Copyright (C) 2001 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
typedef struct _Jbig2ArithState Jbig2ArithState; |
/* An arithmetic coding context is stored as a single byte, with the |
index in the low order 7 bits (actually only 6 are used), and the |
MPS in the top bit. */ |
typedef unsigned char Jbig2ArithCx; |
/* allocate and initialize a new arithmetic coding state */ |
Jbig2ArithState * |
jbig2_arith_new (Jbig2Ctx *ctx, Jbig2WordStream *ws); |
/* decode a bit */ |
bool |
jbig2_arith_decode (Jbig2ArithState *as, Jbig2ArithCx *pcx); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_arith_iaid.c |
---|
0,0 → 1,91 |
/* |
jbig2dec |
Copyright (C) 2001 Artifex Software, Inc. |
This software is provided AS-IS with no warranty, |
either express or implied. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* Annex A.3 */ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> |
#include <string.h> /* memset() */ |
#ifdef VERBOSE |
#include <stdio.h> /* for debug printing only */ |
#endif |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#include "jbig2_arith_iaid.h" |
struct _Jbig2ArithIaidCtx { |
int SBSYMCODELEN; |
Jbig2ArithCx *IAIDx; |
}; |
Jbig2ArithIaidCtx * |
jbig2_arith_iaid_ctx_new(Jbig2Ctx *ctx, int SBSYMCODELEN) |
{ |
Jbig2ArithIaidCtx *result = jbig2_new(ctx, Jbig2ArithIaidCtx, 1); |
int ctx_size = 1 << SBSYMCODELEN; |
result->SBSYMCODELEN = SBSYMCODELEN; |
result->IAIDx = jbig2_alloc(ctx->allocator, ctx_size); |
memset(result->IAIDx, 0, ctx_size); |
return result; |
} |
/* A.3 */ |
/* Return value: -1 on error, 0 on normal value */ |
int |
jbig2_arith_iaid_decode(Jbig2ArithIaidCtx *ctx, Jbig2ArithState *as, |
int32_t *p_result) |
{ |
Jbig2ArithCx *IAIDx = ctx->IAIDx; |
int SBSYMCODELEN = ctx->SBSYMCODELEN; |
int PREV = 1; |
int D; |
int i; |
/* A.3 (2) */ |
for (i = 0; i < SBSYMCODELEN; i++) |
{ |
D = jbig2_arith_decode(as, &IAIDx[PREV]); |
#ifdef VERBOSE |
fprintf(stderr, "IAID%x: D = %d\n", PREV, D); |
#endif |
PREV = (PREV << 1) | D; |
} |
/* A.3 (3) */ |
PREV -= 1 << SBSYMCODELEN; |
#ifdef VERBOSE |
fprintf(stderr, "IAID result: %d\n", PREV); |
#endif |
*p_result = PREV; |
return 0; |
} |
void |
jbig2_arith_iaid_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *iax) |
{ |
jbig2_free(ctx->allocator, iax->IAIDx); |
jbig2_free(ctx->allocator, iax); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_arith_iaid.h |
---|
0,0 → 1,26 |
/* |
jbig2dec |
Copyright (C) 2001 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
typedef struct _Jbig2ArithIaidCtx Jbig2ArithIaidCtx; |
Jbig2ArithIaidCtx * |
jbig2_arith_iaid_ctx_new(Jbig2Ctx *ctx, int SBSYMCODELEN); |
int |
jbig2_arith_iaid_decode(Jbig2ArithIaidCtx *ctx, Jbig2ArithState *as, |
int32_t *p_result); |
void |
jbig2_arith_iaid_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *iax); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_arith_int.c |
---|
0,0 → 1,139 |
/* |
jbig2dec |
Copyright (C) 2001 Artifex Software, Inc. |
This software is provided AS-IS with no warranty, |
either express or implied. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* Annex A */ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> |
#include <string.h> /* memset() */ |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#include "jbig2_arith_int.h" |
struct _Jbig2ArithIntCtx { |
Jbig2ArithCx IAx[512]; |
}; |
Jbig2ArithIntCtx * |
jbig2_arith_int_ctx_new(Jbig2Ctx *ctx) |
{ |
Jbig2ArithIntCtx *result = jbig2_new(ctx, Jbig2ArithIntCtx, 1); |
memset(result->IAx, 0, sizeof(result->IAx)); |
return result; |
} |
/* A.2 */ |
/* Return value: -1 on error, 0 on normal value, 1 on OOB return. */ |
int |
jbig2_arith_int_decode(Jbig2ArithIntCtx *ctx, Jbig2ArithState *as, |
int32_t *p_result) |
{ |
Jbig2ArithCx *IAx = ctx->IAx; |
int PREV = 1; |
int S, V; |
int bit; |
int n_tail, offset; |
int i; |
S = jbig2_arith_decode(as, &IAx[PREV]); |
PREV = (PREV << 1) | S; |
bit = jbig2_arith_decode(as, &IAx[PREV]); |
PREV = (PREV << 1) | bit; |
if (bit) |
{ |
bit = jbig2_arith_decode(as, &IAx[PREV]); |
PREV = (PREV << 1) | bit; |
if (bit) |
{ |
bit = jbig2_arith_decode(as, &IAx[PREV]); |
PREV = (PREV << 1) | bit; |
if (bit) |
{ |
bit = jbig2_arith_decode(as, &IAx[PREV]); |
PREV = (PREV << 1) | bit; |
if (bit) |
{ |
bit = jbig2_arith_decode(as, &IAx[PREV]); |
PREV = (PREV << 1) | bit; |
if (bit) |
{ |
n_tail = 32; |
offset = 4436; |
} |
else |
{ |
n_tail = 12; |
offset = 340; |
} |
} |
else |
{ |
n_tail = 8; |
offset = 84; |
} |
} |
else |
{ |
n_tail = 6; |
offset = 20; |
} |
} |
else |
{ |
n_tail = 4; |
offset = 4; |
} |
} |
else |
{ |
n_tail = 2; |
offset = 0; |
} |
V = 0; |
for (i = 0; i < n_tail; i++) |
{ |
bit = jbig2_arith_decode(as, &IAx[PREV]); |
PREV = ((PREV << 1) & 511) | (PREV & 256) | bit; |
V = (V << 1) | bit; |
} |
V += offset; |
V = S ? -V : V; |
*p_result = V; |
return S && V == 0 ? 1 : 0; |
} |
void |
jbig2_arith_int_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIntCtx *iax) |
{ |
jbig2_free(ctx->allocator, iax); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_arith_int.h |
---|
0,0 → 1,26 |
/* |
jbig2dec |
Copyright (C) 2001 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
typedef struct _Jbig2ArithIntCtx Jbig2ArithIntCtx; |
Jbig2ArithIntCtx * |
jbig2_arith_int_ctx_new(Jbig2Ctx *ctx); |
int |
jbig2_arith_int_decode(Jbig2ArithIntCtx *ctx, Jbig2ArithState *as, |
int32_t *p_result); |
void |
jbig2_arith_int_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIntCtx *iax); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_generic.c |
---|
0,0 → 1,854 |
/* |
jbig2dec |
Copyright (C) 2002-2005 Artifex Software, Inc. |
This software is provided AS-IS with no warranty, |
either express or implied. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/** |
* Generic region handlers. |
**/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> |
#include <string.h> /* memcpy(), memset() */ |
#ifdef OUTPUT_PBM |
#include <stdio.h> |
#endif |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_image.h" |
#include "jbig2_arith.h" |
#include "jbig2_generic.h" |
#include "jbig2_mmr.h" |
/* return the appropriate context size for the given template */ |
int |
jbig2_generic_stats_size(Jbig2Ctx *ctx, int template) |
{ |
int stats_size = template == 0 ? 1 << 16 : |
template == 1 ? 1 << 1 << 13 : 1 << 10; |
return stats_size; |
} |
static int |
jbig2_decode_generic_template0(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
const int rowstride = image->stride; |
int x, y; |
byte *gbreg_line = (byte *)image->data; |
/* todo: currently we only handle the nominal gbat location */ |
#ifdef OUTPUT_PBM |
printf("P4\n%d %d\n", GBW, GBH); |
#endif |
for (y = 0; y < GBH; y++) |
{ |
uint32_t CONTEXT; |
uint32_t line_m1; |
uint32_t line_m2; |
int padded_width = (GBW + 7) & -8; |
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 6 : 0; |
CONTEXT = (line_m1 & 0x7f0) | (line_m2 & 0xf800); |
/* 6.2.5.7 3d */ |
for (x = 0; x < padded_width; x += 8) |
{ |
byte result = 0; |
int x_minor; |
int minor_width = GBW - x > 8 ? 8 : GBW - x; |
if (y >= 1) |
line_m1 = (line_m1 << 8) | |
(x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
if (y >= 2) |
line_m2 = (line_m2 << 8) | |
(x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 6: 0); |
/* This is the speed-critical inner loop. */ |
for (x_minor = 0; x_minor < minor_width; x_minor++) |
{ |
bool bit; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
result |= bit << (7 - x_minor); |
CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit | |
((line_m1 >> (7 - x_minor)) & 0x10) | |
((line_m2 >> (7 - x_minor)) & 0x800); |
} |
gbreg_line[x >> 3] = result; |
} |
#ifdef OUTPUT_PBM |
fwrite(gbreg_line, 1, rowstride, stdout); |
#endif |
gbreg_line += rowstride; |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
uint32_t CONTEXT; |
int x,y; |
bool bit; |
/* this version is generic and easy to understand, but very slow */ |
for (y = 0; y < GBH; y++) { |
for (x = 0; x < GBW; x++) { |
CONTEXT = 0; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
y + params->gbat[1]) << 4; |
CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6; |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 7; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], |
y + params->gbat[3]) << 10; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], |
y + params->gbat[5]) << 11; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12; |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], |
y + params->gbat[7]) << 15; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template1(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
const int rowstride = image->stride; |
int x, y; |
byte *gbreg_line = (byte *)image->data; |
/* todo: currently we only handle the nominal gbat location */ |
#ifdef OUTPUT_PBM |
printf("P4\n%d %d\n", GBW, GBH); |
#endif |
for (y = 0; y < GBH; y++) |
{ |
uint32_t CONTEXT; |
uint32_t line_m1; |
uint32_t line_m2; |
int padded_width = (GBW + 7) & -8; |
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 5 : 0; |
CONTEXT = ((line_m1 >> 1) & 0x1f8) | ((line_m2 >> 1) & 0x1e00); |
/* 6.2.5.7 3d */ |
for (x = 0; x < padded_width; x += 8) |
{ |
byte result = 0; |
int x_minor; |
int minor_width = GBW - x > 8 ? 8 : GBW - x; |
if (y >= 1) |
line_m1 = (line_m1 << 8) | |
(x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
if (y >= 2) |
line_m2 = (line_m2 << 8) | |
(x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 5: 0); |
/* This is the speed-critical inner loop. */ |
for (x_minor = 0; x_minor < minor_width; x_minor++) |
{ |
bool bit; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
result |= bit << (7 - x_minor); |
CONTEXT = ((CONTEXT & 0xefb) << 1) | bit | |
((line_m1 >> (8 - x_minor)) & 0x8) | |
((line_m2 >> (8 - x_minor)) & 0x200); |
} |
gbreg_line[x >> 3] = result; |
} |
#ifdef OUTPUT_PBM |
fwrite(gbreg_line, 1, rowstride, stdout); |
#endif |
gbreg_line += rowstride; |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template2(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
const int rowstride = image->stride; |
int x, y; |
byte *gbreg_line = (byte *)image->data; |
/* todo: currently we only handle the nominal gbat location */ |
#ifdef OUTPUT_PBM |
printf("P4\n%d %d\n", GBW, GBH); |
#endif |
for (y = 0; y < GBH; y++) |
{ |
uint32_t CONTEXT; |
uint32_t line_m1; |
uint32_t line_m2; |
int padded_width = (GBW + 7) & -8; |
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0; |
CONTEXT = ((line_m1 >> 3) & 0x7c) | ((line_m2 >> 3) & 0x380); |
/* 6.2.5.7 3d */ |
for (x = 0; x < padded_width; x += 8) |
{ |
byte result = 0; |
int x_minor; |
int minor_width = GBW - x > 8 ? 8 : GBW - x; |
if (y >= 1) |
line_m1 = (line_m1 << 8) | |
(x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
if (y >= 2) |
line_m2 = (line_m2 << 8) | |
(x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0); |
/* This is the speed-critical inner loop. */ |
for (x_minor = 0; x_minor < minor_width; x_minor++) |
{ |
bool bit; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
result |= bit << (7 - x_minor); |
CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit | |
((line_m1 >> (10 - x_minor)) & 0x4) | |
((line_m2 >> (10 - x_minor)) & 0x80); |
} |
gbreg_line[x >> 3] = result; |
} |
#ifdef OUTPUT_PBM |
fwrite(gbreg_line, 1, rowstride, stdout); |
#endif |
gbreg_line += rowstride; |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template2a(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
const int rowstride = image->stride; |
int x, y; |
byte *gbreg_line = (byte *)image->data; |
/* This is a special case for GBATX1 = 3, GBATY1 = -1 */ |
#ifdef OUTPUT_PBM |
printf("P4\n%d %d\n", GBW, GBH); |
#endif |
for (y = 0; y < GBH; y++) |
{ |
uint32_t CONTEXT; |
uint32_t line_m1; |
uint32_t line_m2; |
int padded_width = (GBW + 7) & -8; |
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0; |
CONTEXT = ((line_m1 >> 3) & 0x78) | ((line_m1 >> 2) & 0x4) | ((line_m2 >> 3) & 0x380); |
/* 6.2.5.7 3d */ |
for (x = 0; x < padded_width; x += 8) |
{ |
byte result = 0; |
int x_minor; |
int minor_width = GBW - x > 8 ? 8 : GBW - x; |
if (y >= 1) |
line_m1 = (line_m1 << 8) | |
(x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
if (y >= 2) |
line_m2 = (line_m2 << 8) | |
(x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0); |
/* This is the speed-critical inner loop. */ |
for (x_minor = 0; x_minor < minor_width; x_minor++) |
{ |
bool bit; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
result |= bit << (7 - x_minor); |
CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit | |
((line_m1 >> (10 - x_minor)) & 0x8) | |
((line_m1 >> (9 - x_minor)) & 0x4) | |
((line_m2 >> (10 - x_minor)) & 0x80); |
} |
gbreg_line[x >> 3] = result; |
} |
#ifdef OUTPUT_PBM |
fwrite(gbreg_line, 1, rowstride, stdout); |
#endif |
gbreg_line += rowstride; |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template3(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
const int rowstride = image->stride; |
byte *gbreg_line = (byte *)image->data; |
int x, y; |
/* this routine only handles the nominal AT location */ |
#ifdef OUTPUT_PBM |
printf("P4\n%d %d\n", GBW, GBH); |
#endif |
for (y = 0; y < GBH; y++) |
{ |
uint32_t CONTEXT; |
uint32_t line_m1; |
int padded_width = (GBW + 7) & -8; |
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
CONTEXT = (line_m1 >> 1) & 0x3f0; |
/* 6.2.5.7 3d */ |
for (x = 0; x < padded_width; x += 8) |
{ |
byte result = 0; |
int x_minor; |
int minor_width = GBW - x > 8 ? 8 : GBW - x; |
if (y >= 1) |
line_m1 = (line_m1 << 8) | |
(x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
/* This is the speed-critical inner loop. */ |
for (x_minor = 0; x_minor < minor_width; x_minor++) |
{ |
bool bit; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
result |= bit << (7 - x_minor); |
CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit | |
((line_m1 >> (10 - x_minor)) & 0x010); |
} |
gbreg_line[x >> 3] = result; |
} |
#ifdef OUTPUT_PBM |
fwrite(gbreg_line, 1, rowstride, stdout); |
#endif |
gbreg_line += rowstride; |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template3_unopt(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
uint32_t CONTEXT; |
int x,y; |
bool bit; |
/* this version is generic and easy to understand, but very slow */ |
for (y = 0; y < GBH; y++) { |
for (x = 0; x < GBW; x++) { |
CONTEXT = 0; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
y + params->gbat[1]) << 4; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5; |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8; |
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} |
return 0; |
} |
static void |
copy_prev_row(Jbig2Image *image, int row) |
{ |
if (!row) { |
/* no previous row */ |
memset( image->data, 0, image->stride ); |
} else { |
/* duplicate data from the previous row */ |
uint8_t *src = image->data + (row - 1) * image->stride; |
memcpy( src + image->stride, src, image->stride ); |
} |
} |
static int |
jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
uint32_t CONTEXT; |
int x, y; |
bool bit; |
int LTP = 0; |
for (y = 0; y < GBH; y++) |
{ |
LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25]); |
if (!LTP) { |
for (x = 0; x < GBW; x++) { |
CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
y + params->gbat[1]) << 4; |
CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6; |
CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 7; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], |
y + params->gbat[3]) << 10; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], |
y + params->gbat[5]) << 11; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12; |
CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 13; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], |
y + params->gbat[7]) << 15; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} else { |
copy_prev_row(image, y); |
} |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
uint32_t CONTEXT; |
int x, y; |
bool bit; |
int LTP = 0; |
for (y = 0; y < GBH; y++) { |
LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795]); |
if (!LTP) { |
for (x = 0; x < GBW; x++) { |
CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
y + params->gbat[1]) << 3; |
CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5; |
CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 6; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8; |
CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10; |
CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 11; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} else { |
copy_prev_row(image, y); |
} |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
uint32_t CONTEXT; |
int x, y; |
bool bit; |
int LTP = 0; |
for (y = 0; y < GBH; y++) { |
LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5]); |
if (!LTP) { |
for (x = 0; x < GBW; x++) { |
CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
y + params->gbat[1]) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3; |
CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 4; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7; |
CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 8; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} else { |
copy_prev_row(image, y); |
} |
} |
return 0; |
} |
static int |
jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int GBW = image->width; |
const int GBH = image->height; |
uint32_t CONTEXT; |
int x, y; |
bool bit; |
int LTP = 0; |
for (y = 0; y < GBH; y++) { |
LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195]); |
if (!LTP) { |
for (x = 0; x < GBW; x++) { |
CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
y + params->gbat[1]) << 4; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5; |
CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 6; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7; |
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8; |
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9; |
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} else { |
copy_prev_row(image, y); |
} |
} |
return 0; |
} |
static int |
jbig2_decode_generic_region_TPGDON(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
switch (params->GBTEMPLATE) { |
case 0: |
return jbig2_decode_generic_template0_TPGDON(ctx, segment, |
params, as, image, GB_stats); |
case 1: |
return jbig2_decode_generic_template1_TPGDON(ctx, segment, |
params, as, image, GB_stats); |
case 2: |
return jbig2_decode_generic_template2_TPGDON(ctx, segment, |
params, as, image, GB_stats); |
case 3: |
return jbig2_decode_generic_template3_TPGDON(ctx, segment, |
params, as, image, GB_stats); |
} |
return -1; |
} |
/** |
* jbig2_decode_generic_region: Decode a generic region. |
* @ctx: The context for allocation and error reporting. |
* @segment: A segment reference for error reporting. |
* @params: Decoding parameter set. |
* @as: Arithmetic decoder state. |
* @image: Where to store the decoded data. |
* @GB_stats: Arithmetic stats. |
* |
* Decodes a generic region, according to section 6.2. The caller should |
* pass an already allocated Jbig2Image object for @image |
* |
* Because this API is based on an arithmetic decoding state, it is |
* not suitable for MMR decoding. |
* |
* Return code: 0 on success. |
**/ |
int |
jbig2_decode_generic_region(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
const int8_t *gbat = params->gbat; |
if (!params->MMR && params->TPGDON) |
return jbig2_decode_generic_region_TPGDON(ctx, segment, params, |
as, image, GB_stats); |
if (!params->MMR && params->GBTEMPLATE == 0) { |
if (gbat[0] == +3 && gbat[1] == -1 && |
gbat[2] == -3 && gbat[3] == -1 && |
gbat[4] == +2 && gbat[5] == -2 && |
gbat[6] == -2 && gbat[7] == -2) |
return jbig2_decode_generic_template0(ctx, segment, params, |
as, image, GB_stats); |
else |
return jbig2_decode_generic_template0_unopt(ctx, segment, params, |
as, image, GB_stats); |
} else if (!params->MMR && params->GBTEMPLATE == 1) |
return jbig2_decode_generic_template1(ctx, segment, params, |
as, image, GB_stats); |
else if (!params->MMR && params->GBTEMPLATE == 2) |
{ |
if (gbat[0] == 3 && gbat[1] == -1) |
return jbig2_decode_generic_template2a(ctx, segment, params, |
as, image, GB_stats); |
else |
return jbig2_decode_generic_template2(ctx, segment, params, |
as, image, GB_stats); |
} |
else if (!params->MMR && params->GBTEMPLATE == 3) { |
if (gbat[0] == 2 && gbat[1] == -1) |
return jbig2_decode_generic_template3_unopt(ctx, segment, params, |
as, image, GB_stats); |
else |
return jbig2_decode_generic_template3_unopt(ctx, segment, params, |
as, image, GB_stats); |
} |
{ |
int i; |
for (i = 0; i < 8; i++) |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"gbat[%d] = %d", i, params->gbat[i]); |
} |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"decode_generic_region: MMR=%d, GBTEMPLATE=%d NYI", |
params->MMR, params->GBTEMPLATE); |
return -1; |
} |
/** |
* Handler for immediate generic region segments |
*/ |
int |
jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data) |
{ |
Jbig2RegionSegmentInfo rsi; |
byte seg_flags; |
int8_t gbat[8]; |
int offset; |
int gbat_bytes = 0; |
Jbig2GenericRegionParams params; |
int code; |
Jbig2Image *image; |
Jbig2WordStream *ws; |
Jbig2ArithState *as; |
Jbig2ArithCx *GB_stats = NULL; |
/* 7.4.6 */ |
if (segment->data_length < 18) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
jbig2_get_region_segment_info(&rsi, segment_data); |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"generic region: %d x %d @ (%d, %d), flags = %02x", |
rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags); |
/* 7.4.6.2 */ |
seg_flags = segment_data[17]; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"segment flags = %02x", seg_flags); |
if ((seg_flags & 1) && (seg_flags & 6)) |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"MMR is 1, but GBTEMPLATE is not 0"); |
/* 7.4.6.3 */ |
if (!(seg_flags & 1)) |
{ |
gbat_bytes = (seg_flags & 6) ? 2 : 8; |
if (18 + gbat_bytes > segment->data_length) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
memcpy(gbat, segment_data + 18, gbat_bytes); |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"gbat: %d, %d", gbat[0], gbat[1]); |
} |
offset = 18 + gbat_bytes; |
/* Table 34 */ |
params.MMR = seg_flags & 1; |
params.GBTEMPLATE = (seg_flags & 6) >> 1; |
params.TPGDON = (seg_flags & 8) >> 3; |
params.USESKIP = 0; |
memcpy (params.gbat, gbat, gbat_bytes); |
image = jbig2_image_new(ctx, rsi.width, rsi.height); |
if (image == NULL) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"unable to allocate generic image"); |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"allocated %d x %d image buffer for region decode results", |
rsi.width, rsi.height); |
if (params.MMR) |
{ |
code = jbig2_decode_generic_mmr(ctx, segment, ¶ms, |
segment_data + offset, segment->data_length - offset, |
image); |
} |
else |
{ |
int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE); |
GB_stats = jbig2_alloc(ctx->allocator, stats_size); |
memset(GB_stats, 0, stats_size); |
ws = jbig2_word_stream_buf_new(ctx, |
segment_data + offset, |
segment->data_length - offset); |
as = jbig2_arith_new(ctx, ws); |
code = jbig2_decode_generic_region(ctx, segment, ¶ms, |
as, image, GB_stats); |
jbig2_free(ctx->allocator, as); |
jbig2_word_stream_buf_free(ctx, ws); |
jbig2_free(ctx->allocator, GB_stats); |
} |
jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], |
image, rsi.x, rsi.y, JBIG2_COMPOSE_OR); |
jbig2_image_release(ctx, image); |
return code; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_generic.h |
---|
0,0 → 1,62 |
/* |
jbig2dec |
Copyright (C) 2002-2004 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/** |
* Headers for Generic and Generic Refinement region handling |
**/ |
/* 6.4 Table 2 */ |
typedef struct { |
bool MMR; |
/* GBW */ |
/* GBH */ |
int GBTEMPLATE; |
bool TPGDON; |
bool USESKIP; |
/* SKIP */ |
int8_t gbat[8]; |
} Jbig2GenericRegionParams; |
/* return the appropriate context size for the given template */ |
int |
jbig2_generic_stats_size(Jbig2Ctx *ctx, int template); |
int |
jbig2_decode_generic_region(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats); |
/* 6.3 Table 6 */ |
typedef struct { |
/* GRW */ |
/* GRH */ |
bool GRTEMPLATE; |
Jbig2Image *reference; |
int32_t DX, DY; |
bool TPGRON; |
int8_t grat[4]; |
} Jbig2RefinementRegionParams; |
int |
jbig2_decode_refinement_region(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2RefinementRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_halftone.c |
---|
0,0 → 1,372 |
/* |
jbig2dec |
Copyright (C) 2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* JBIG2 Pattern Dictionary and Halftone Region decoding */ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <string.h> /* memset() */ |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#include "jbig2_generic.h" |
#include "jbig2_mmr.h" |
typedef struct { |
int n_patterns; |
Jbig2Image **patterns; |
int HPW, HPH; |
} Jbig2PatternDict; |
/* Table 24 */ |
typedef struct { |
bool HDMMR; |
uint32_t HDPW; |
uint32_t HDPH; |
uint32_t GRAYMAX; |
int HDTEMPLATE; |
} Jbig2PatternDictParams; |
/* Table 33 */ |
typedef struct { |
byte flags; |
uint32_t HGW; |
uint32_t HGH; |
int32_t HGX; |
int32_t HGY; |
uint16_t HRX; |
uint16_t HRY; |
bool HMMR; |
int HTEMPLATE; |
bool HENABLESKIP; |
Jbig2ComposeOp op; |
bool HDEFPIXEL; |
} Jbig2HalftoneRegionParams; |
/** |
* jbig2_hd_new: create a new dictionary from a collective bitmap |
*/ |
Jbig2PatternDict * |
jbig2_hd_new(Jbig2Ctx *ctx, |
const Jbig2PatternDictParams *params, |
Jbig2Image *image) |
{ |
Jbig2PatternDict *new; |
const int N = params->GRAYMAX + 1; |
const int HPW = params->HDPW; |
const int HPH = params->HDPH; |
int i; |
/* allocate a new struct */ |
new = (Jbig2PatternDict *)jbig2_alloc(ctx->allocator, |
sizeof(Jbig2PatternDict)); |
if (new != NULL) { |
new->patterns = (Jbig2Image **)jbig2_alloc(ctx->allocator, |
N*sizeof(Jbig2Image*)); |
if (new->patterns == NULL) { |
jbig2_free(ctx->allocator, new); |
return NULL; |
} |
new->n_patterns = N; |
new->HPW = HPW; |
new->HPH = HPH; |
/* 6.7.5(4) - copy out the individual pattern images */ |
for (i = 0; i < N; i++) { |
new->patterns[i] = jbig2_image_new(ctx, HPW, HPH); |
if (new->patterns[i] == NULL) { |
int j; |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"failed to allocate pattern element image"); |
for (j = 0; j < i; j++) |
jbig2_free(ctx->allocator, new->patterns[j]); |
jbig2_free(ctx->allocator, new); |
return NULL; |
} |
/* compose with the REPLACE operator; the source |
will be clipped to the destintion, selecting the |
proper sub image */ |
jbig2_image_compose(ctx, new->patterns[i], image, |
-i * HPW, 0, JBIG2_COMPOSE_REPLACE); |
} |
} |
return new; |
} |
/** |
* jbig2_hd_release: release a pattern dictionary |
*/ |
void |
jbig2_hd_release(Jbig2Ctx *ctx, Jbig2PatternDict *dict) |
{ |
int i; |
if (dict == NULL) return; |
for (i = 0; i < dict->n_patterns; i++) |
if (dict->patterns[i]) jbig2_image_release(ctx, dict->patterns[i]); |
jbig2_free(ctx->allocator, dict->patterns); |
jbig2_free(ctx->allocator, dict); |
} |
/** |
* jbig2_decode_pattern_dict: decode pattern dictionary data |
* |
* @ctx: jbig2 decoder context |
* @segment: jbig2 segment (header) structure |
* @params: parameters from the pattern dictionary header |
* @data: pointer to text region data to be decoded |
* @size: length of text region data |
* @GB_stats: artimetic coding context to use |
* |
* Implements the patten dictionary decoding proceedure |
* described in section 6.7 of the JBIG2 spec. |
* |
* returns: a pointer to the resulting dictionary on success |
* returns: 0 on failure |
**/ |
static Jbig2PatternDict * |
jbig2_decode_pattern_dict(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const Jbig2PatternDictParams *params, |
const byte *data, const size_t size, |
Jbig2ArithCx *GB_stats) |
{ |
Jbig2PatternDict *hd = NULL; |
Jbig2Image *image; |
Jbig2GenericRegionParams rparams; |
int code; |
/* allocate the collective image */ |
image = jbig2_image_new(ctx, |
params->HDPW * (params->GRAYMAX + 1), params->HDPH); |
if (image == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"failed to allocate collective bitmap for halftone dict!"); |
return NULL; |
} |
/* fill out the generic region decoder parameters */ |
rparams.MMR = params->HDMMR; |
rparams.GBTEMPLATE = params->HDTEMPLATE; |
rparams.TPGDON = 0; /* not used if HDMMR = 1 */ |
rparams.USESKIP = 0; |
rparams.gbat[0] = -params->HDPW; |
rparams.gbat[1] = 0; |
rparams.gbat[2] = -3; |
rparams.gbat[3] = -1; |
rparams.gbat[4] = 2; |
rparams.gbat[5] = -2; |
rparams.gbat[6] = -2; |
rparams.gbat[7] = -2; |
if (params->HDMMR) { |
code = jbig2_decode_generic_mmr(ctx, segment, &rparams, |
data, size, image); |
} else { |
Jbig2WordStream *ws = jbig2_word_stream_buf_new(ctx, data, size); |
Jbig2ArithState *as = jbig2_arith_new(ctx, ws); |
code = jbig2_decode_generic_region(ctx, segment, &rparams, |
as, image, GB_stats); |
jbig2_free(ctx->allocator, as); |
jbig2_word_stream_buf_free(ctx, ws); |
} |
if (code != 0) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"error decoding collective pattern dictionary bitmap!"); |
} |
hd = jbig2_hd_new(ctx, params, image); |
jbig2_image_release(ctx, image); |
return hd; |
} |
/* 7.4.4 */ |
int |
jbig2_pattern_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data) |
{ |
Jbig2PatternDictParams params; |
Jbig2ArithCx *GB_stats = NULL; |
byte flags; |
int offset = 0; |
/* 7.4.4.1 - Data header */ |
if (segment->data_length < 7) { |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
} |
flags = segment_data[0]; |
params.HDMMR = flags & 1; |
params.HDTEMPLATE = (flags & 6) >> 1; |
params.HDPW = segment_data[1]; |
params.HDPH = segment_data[2]; |
params.GRAYMAX = jbig2_get_int32(segment_data + 3); |
offset += 7; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"pattern dictionary, flags=%02x, %d grays (%dx%d cell)", |
flags, params.GRAYMAX + 1, params.HDPW, params.HDPH); |
if (params.HDMMR && params.HDTEMPLATE) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"HDTEMPLATE is %d when HDMMR is %d, contrary to spec", |
params.HDTEMPLATE, params.HDMMR); |
} |
if (flags & 0xf8) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"Reserved flag bits non-zero"); |
} |
/* 7.4.4.2 */ |
if (!params.HDMMR) { |
/* allocate and zero arithmetic coding stats */ |
int stats_size = jbig2_generic_stats_size(ctx, params.HDTEMPLATE); |
GB_stats = jbig2_alloc(ctx->allocator, stats_size); |
memset(GB_stats, 0, stats_size); |
} |
segment->result = jbig2_decode_pattern_dict(ctx, segment, ¶ms, |
segment_data + offset, |
segment->data_length - offset, GB_stats); |
/* todo: retain GB_stats? */ |
if (!params.HDMMR) { |
jbig2_free(ctx->allocator, GB_stats); |
} |
return (segment->result != NULL) ? 0 : 1; |
} |
/** |
* jbig2_decode_halftone_region: decode a halftone region |
**/ |
int |
jbig2_decode_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
Jbig2HalftoneRegionParams *params, |
const byte *data, const size_t size, |
Jbig2Image *image, |
Jbig2ArithCx *GB_stats) |
{ |
int code = 0; |
/* todo: implement */ |
return code; |
} |
/** |
* jbig2_halftone_region: read a halftone region segment header |
**/ |
int |
jbig2_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data) |
{ |
int offset = 0; |
Jbig2RegionSegmentInfo region_info; |
Jbig2HalftoneRegionParams params; |
Jbig2Image *image; |
Jbig2ArithCx *GB_stats; |
int code; |
/* 7.4.5.1 */ |
if (segment->data_length < 17) goto too_short; |
jbig2_get_region_segment_info(®ion_info, segment_data); |
offset += 17; |
if (segment->data_length < 18) goto too_short; |
/* 7.4.5.1.1 */ |
params.flags = segment_data[offset]; |
params.HMMR = params.flags & 1; |
params.HTEMPLATE = (params.flags & 6) >> 1; |
params.HENABLESKIP = (params.flags & 8) >> 3; |
params.op = (params.flags & 0x70) >> 4; |
params.HDEFPIXEL = (params.flags &0x80) >> 7; |
offset += 1; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"halftone region: %d x %d @ (%x,%d) flags=%02x", |
region_info.width, region_info.height, |
region_info.x, region_info.y, params.flags); |
if (params.HMMR && params.HTEMPLATE) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"HTEMPLATE is %d when HMMR is %d, contrary to spec", |
params.HTEMPLATE, params.HMMR); |
} |
if (params.HMMR && params.HENABLESKIP) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"HENABLESKIP is %d when HMMR is %d, contrary to spec", |
params.HENABLESKIP, params.HMMR); |
} |
/* Figure 43 */ |
if (segment->data_length - offset < 16) goto too_short; |
params.HGW = jbig2_get_int32(segment_data + offset); |
params.HGH = jbig2_get_int32(segment_data + offset + 4); |
params.HGX = jbig2_get_int32(segment_data + offset + 8); |
params.HGY = jbig2_get_int32(segment_data + offset + 12); |
offset += 16; |
/* Figure 44 */ |
if (segment->data_length - offset < 4) goto too_short; |
params.HRX = jbig2_get_int16(segment_data + offset); |
params.HRY = jbig2_get_int16(segment_data + offset + 2); |
offset += 4; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
" grid %d x %d @ (%d.%d,%d.%d) vector (%d.%d,%d.%d)", |
params.HGW, params.HGH, |
params.HGX >> 8, params.HGX & 0xff, |
params.HGY >> 8, params.HGY & 0xff, |
params.HRX >> 8, params.HRX & 0xff, |
params.HRY >> 8, params.HRY & 0xff); |
/* 7.4.5.2.2 */ |
if (!params.HMMR) { |
/* allocate and zero arithmetic coding stats */ |
int stats_size = jbig2_generic_stats_size(ctx, params.HTEMPLATE); |
GB_stats = jbig2_alloc(ctx->allocator, stats_size); |
memset(GB_stats, 0, stats_size); |
} |
image = jbig2_image_new(ctx, region_info.width, region_info.height); |
if (image == NULL) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"unable to allocate halftone image"); |
code = jbig2_decode_halftone_region(ctx, segment, ¶ms, |
segment_data + offset, segment->data_length - offset, |
image, GB_stats); |
/* todo: retain GB_stats? */ |
if (!params.HMMR) { |
jbig2_free(ctx->allocator, GB_stats); |
} |
return code; |
too_short: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_huffman.c |
---|
0,0 → 1,480 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* Huffman table decoding procedures |
-- See Annex B of the JBIG2 specification */ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stdlib.h> |
#include <string.h> |
#ifdef JBIG2_DEBUG |
#include <stdio.h> |
#endif |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_huffman.h" |
#include "jbig2_hufftab.h" |
#define JBIG2_HUFFMAN_FLAGS_ISOOB 1 |
#define JBIG2_HUFFMAN_FLAGS_ISLOW 2 |
#define JBIG2_HUFFMAN_FLAGS_ISEXT 4 |
struct _Jbig2HuffmanState { |
/* The current bit offset is equal to (offset * 8) + offset_bits. |
The MSB of this_word is the current bit offset. The MSB of next_word |
is (offset + 4) * 8. */ |
uint32_t this_word; |
uint32_t next_word; |
int offset_bits; |
int offset; |
Jbig2WordStream *ws; |
}; |
/** Allocate and initialize a new huffman coding state |
* the returned pointer can simply be freed; this does |
* not affect the associated Jbig2WordStream. |
*/ |
Jbig2HuffmanState * |
jbig2_huffman_new (Jbig2Ctx *ctx, Jbig2WordStream *ws) |
{ |
Jbig2HuffmanState *result; |
result = (Jbig2HuffmanState *)jbig2_alloc(ctx->allocator, |
sizeof(Jbig2HuffmanState)); |
if (result != NULL) { |
result->offset = 0; |
result->offset_bits = 0; |
result->this_word = ws->get_next_word (ws, 0); |
result->next_word = ws->get_next_word (ws, 4); |
result->ws = ws; |
} |
return result; |
} |
/** Free an allocated huffman coding state. |
* This just calls jbig2_free() if the pointer is not NULL |
*/ |
void |
jbig2_huffman_free (Jbig2Ctx *ctx, Jbig2HuffmanState *hs) |
{ |
if (hs != NULL) free(hs); |
return; |
} |
/** debug routines **/ |
#ifdef JBIG2_DEBUG |
/** print current huffman state */ |
void jbig2_dump_huffman_state(Jbig2HuffmanState *hs) { |
fprintf(stderr, "huffman state %08x %08x offset %d.%d\n", |
hs->this_word, hs->next_word, hs->offset, hs->offset_bits); |
} |
/** print the binary string we're reading from */ |
void jbig2_dump_huffman_binary(Jbig2HuffmanState *hs) |
{ |
const uint32_t word = hs->this_word; |
int i; |
fprintf(stderr, "huffman binary "); |
for (i = 31; i >= 0; i--) |
fprintf(stderr, ((word >> i) & 1) ? "1" : "0"); |
fprintf(stderr, "\n"); |
} |
#endif /* JBIG2_DEBUG */ |
/** Skip bits up to the next byte boundary |
*/ |
void |
jbig2_huffman_skip(Jbig2HuffmanState *hs) |
{ |
int bits = hs->offset_bits & 7; |
if (bits) { |
bits = 8 - bits; |
hs->offset_bits += bits; |
hs->this_word = (hs->this_word << bits) | |
(hs->next_word >> (32 - hs->offset_bits)); |
} |
if (hs->offset_bits >= 32) { |
Jbig2WordStream *ws = hs->ws; |
hs->this_word = hs->next_word; |
hs->offset += 4; |
hs->next_word = ws->get_next_word (ws, hs->offset + 4); |
hs->offset_bits -= 32; |
if (hs->offset_bits) { |
hs->this_word = (hs->this_word << hs->offset_bits) | |
(hs->next_word >> (32 - hs->offset_bits)); |
} |
} |
} |
/* skip ahead a specified number of bytes in the word stream |
*/ |
void jbig2_huffman_advance(Jbig2HuffmanState *hs, int offset) |
{ |
Jbig2WordStream *ws = hs->ws; |
hs->offset += offset & ~3; |
hs->offset_bits += (offset & 3) << 3; |
if (hs->offset_bits >= 32) { |
hs->offset += 4; |
hs->offset_bits -= 32; |
} |
hs->this_word = ws->get_next_word (ws, hs->offset); |
hs->next_word = ws->get_next_word (ws, hs->offset + 4); |
if (hs->offset_bits > 0) |
hs->this_word = (hs->this_word << hs->offset_bits) | |
(hs->next_word >> (32 - hs->offset_bits)); |
} |
/* return the offset of the huffman decode pointer (in bytes) |
* from the beginning of the WordStream |
*/ |
int |
jbig2_huffman_offset(Jbig2HuffmanState *hs) |
{ |
return hs->offset + (hs->offset_bits >> 3); |
} |
/* read a number of bits directly from the huffman state |
* without decoding against a table |
*/ |
int32_t |
jbig2_huffman_get_bits (Jbig2HuffmanState *hs, const int bits) |
{ |
uint32_t this_word = hs->this_word; |
int32_t result; |
result = this_word >> (32 - bits); |
hs->offset_bits += bits; |
if (hs->offset_bits >= 32) { |
hs->offset += 4; |
hs->offset_bits -= 32; |
hs->this_word = hs->next_word; |
hs->next_word = hs->ws->get_next_word(hs->ws, hs->offset + 4); |
if (hs->offset_bits) { |
hs->this_word = (hs->this_word << hs->offset_bits) | |
(hs->next_word >> (32 - hs->offset_bits)); |
} else { |
hs->this_word = (hs->this_word << hs->offset_bits); |
} |
} else { |
hs->this_word = (this_word << bits) | |
(hs->next_word >> (32 - hs->offset_bits)); |
} |
return result; |
} |
int32_t |
jbig2_huffman_get (Jbig2HuffmanState *hs, |
const Jbig2HuffmanTable *table, bool *oob) |
{ |
Jbig2HuffmanEntry *entry; |
byte flags; |
int offset_bits = hs->offset_bits; |
uint32_t this_word = hs->this_word; |
uint32_t next_word; |
int RANGELEN; |
int32_t result; |
for (;;) |
{ |
int log_table_size = table->log_table_size; |
int PREFLEN; |
entry = &table->entries[this_word >> (32 - log_table_size)]; |
flags = entry->flags; |
PREFLEN = entry->PREFLEN; |
next_word = hs->next_word; |
offset_bits += PREFLEN; |
if (offset_bits >= 32) |
{ |
Jbig2WordStream *ws = hs->ws; |
this_word = next_word; |
hs->offset += 4; |
next_word = ws->get_next_word (ws, hs->offset + 4); |
offset_bits -= 32; |
hs->next_word = next_word; |
PREFLEN = offset_bits; |
} |
if (PREFLEN) |
this_word = (this_word << PREFLEN) | |
(next_word >> (32 - offset_bits)); |
if (flags & JBIG2_HUFFMAN_FLAGS_ISEXT) |
{ |
table = entry->u.ext_table; |
} |
else |
break; |
} |
result = entry->u.RANGELOW; |
RANGELEN = entry->RANGELEN; |
if (RANGELEN > 0) |
{ |
int32_t HTOFFSET; |
HTOFFSET = this_word >> (32 - RANGELEN); |
if (flags & JBIG2_HUFFMAN_FLAGS_ISLOW) |
result -= HTOFFSET; |
else |
result += HTOFFSET; |
offset_bits += RANGELEN; |
if (offset_bits >= 32) |
{ |
Jbig2WordStream *ws = hs->ws; |
this_word = next_word; |
hs->offset += 4; |
next_word = ws->get_next_word (ws, hs->offset + 4); |
offset_bits -= 32; |
hs->next_word = next_word; |
RANGELEN = offset_bits; |
} |
if (RANGELEN) |
this_word = (this_word << RANGELEN) | |
(next_word >> (32 - offset_bits)); |
} |
hs->this_word = this_word; |
hs->offset_bits = offset_bits; |
if (oob != NULL) |
*oob = (flags & JBIG2_HUFFMAN_FLAGS_ISOOB); |
return result; |
} |
/* TODO: more than 8 bits here is wasteful of memory. We have support |
for sub-trees in jbig2_huffman_get() above, but don't use it here. |
We should, and then revert to 8 bits */ |
#define LOG_TABLE_SIZE_MAX 16 |
/** Build an in-memory representation of a Huffman table from the |
* set of template params provided by the spec or a table segment |
*/ |
Jbig2HuffmanTable * |
jbig2_build_huffman_table (Jbig2Ctx *ctx, const Jbig2HuffmanParams *params) |
{ |
int *LENCOUNT; |
int LENMAX = -1; |
const int lencountsize = 256 * sizeof(*LENCOUNT); |
const Jbig2HuffmanLine *lines = params->lines; |
int n_lines = params->n_lines; |
int i, j; |
int max_j; |
int log_table_size = 0; |
Jbig2HuffmanTable *result; |
Jbig2HuffmanEntry *entries; |
int CURLEN; |
int firstcode = 0; |
int CURCODE; |
int CURTEMP; |
LENCOUNT = jbig2_alloc(ctx->allocator, lencountsize); |
if (LENCOUNT == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"couldn't allocate storage for huffman histogram"); |
return NULL; |
} |
memset(LENCOUNT, 0, lencountsize); |
/* B.3, 1. */ |
for (i = 0; i < params->n_lines; i++) |
{ |
int PREFLEN = lines[i].PREFLEN; |
int lts; |
if (PREFLEN > LENMAX) |
{ |
for (j = LENMAX + 1; j < PREFLEN + 1; j++) |
LENCOUNT[j] = 0; |
LENMAX = PREFLEN; |
} |
LENCOUNT[PREFLEN]++; |
lts = PREFLEN + lines[i].RANGELEN; |
if (lts > LOG_TABLE_SIZE_MAX) |
lts = PREFLEN; |
if (lts <= LOG_TABLE_SIZE_MAX && log_table_size < lts) |
log_table_size = lts; |
} |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, |
"constructing huffman table log size %d", log_table_size); |
max_j = 1 << log_table_size; |
result = (Jbig2HuffmanTable *)jbig2_alloc(ctx->allocator, sizeof(Jbig2HuffmanTable)); |
result->log_table_size = log_table_size; |
entries = (Jbig2HuffmanEntry *)jbig2_alloc(ctx->allocator, max_j * sizeof(Jbig2HuffmanEntry)); |
result->entries = entries; |
LENCOUNT[0] = 0; |
for (CURLEN = 1; CURLEN <= LENMAX; CURLEN++) |
{ |
int shift = log_table_size - CURLEN; |
/* B.3 3.(a) */ |
firstcode = (firstcode + LENCOUNT[CURLEN - 1]) << 1; |
CURCODE = firstcode; |
/* B.3 3.(b) */ |
for (CURTEMP = 0; CURTEMP < n_lines; CURTEMP++) |
{ |
int PREFLEN = lines[CURTEMP].PREFLEN; |
if (PREFLEN == CURLEN) |
{ |
int RANGELEN = lines[CURTEMP].RANGELEN; |
int start_j = CURCODE << shift; |
int end_j = (CURCODE + 1) << shift; |
byte eflags = 0; |
if (end_j > max_j) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"ran off the end of the entries table! (%d >= %d)", |
end_j, max_j); |
jbig2_free(ctx->allocator, result->entries); |
jbig2_free(ctx->allocator, result); |
jbig2_free(ctx->allocator, LENCOUNT); |
return NULL; |
} |
/* todo: build extension tables */ |
if (params->HTOOB && CURTEMP == n_lines - 1) |
eflags |= JBIG2_HUFFMAN_FLAGS_ISOOB; |
if (CURTEMP == n_lines - (params->HTOOB ? 3 : 2)) |
eflags |= JBIG2_HUFFMAN_FLAGS_ISLOW; |
if (PREFLEN + RANGELEN > LOG_TABLE_SIZE_MAX) { |
for (j = start_j; j < end_j; j++) { |
entries[j].u.RANGELOW = lines[CURTEMP].RANGELOW; |
entries[j].PREFLEN = PREFLEN; |
entries[j].RANGELEN = RANGELEN; |
entries[j].flags = eflags; |
} |
} else { |
for (j = start_j; j < end_j; j++) { |
int32_t HTOFFSET = (j >> (shift - RANGELEN)) & |
((1 << RANGELEN) - 1); |
if (eflags & JBIG2_HUFFMAN_FLAGS_ISLOW) |
entries[j].u.RANGELOW = lines[CURTEMP].RANGELOW - |
HTOFFSET; |
else |
entries[j].u.RANGELOW = lines[CURTEMP].RANGELOW + |
HTOFFSET; |
entries[j].PREFLEN = PREFLEN + RANGELEN; |
entries[j].RANGELEN = 0; |
entries[j].flags = eflags; |
} |
} |
CURCODE++; |
} |
} |
} |
jbig2_free(ctx->allocator, LENCOUNT); |
return result; |
} |
/** Free the memory associated with the representation of table */ |
void |
jbig2_release_huffman_table (Jbig2Ctx *ctx, Jbig2HuffmanTable *table) |
{ |
if (table != NULL) { |
jbig2_free(ctx->allocator, table->entries); |
jbig2_free(ctx->allocator, table); |
} |
return; |
} |
#ifdef TEST |
#include <stdio.h> |
/* a test bitstream, and a list of the table indicies |
to use in decoding it. 1 = table B.1 (A), 2 = table B.2 (B), and so on */ |
/* this test stream should decode to { 8, 5, oob, 8 } */ |
const byte test_stream[] = { 0xe9, 0xcb, 0xf4, 0x00 }; |
const byte test_tabindex[] = { 4, 2, 2, 1 }; |
static uint32_t |
test_get_word (Jbig2WordStream *self, int offset) |
{ |
/* assume test_stream[] is at least 4 bytes */ |
if (offset+3 > sizeof(test_stream)) |
return 0; |
else |
return ( (test_stream[offset] << 24) | |
(test_stream[offset+1] << 16) | |
(test_stream[offset+2] << 8) | |
(test_stream[offset+3]) ); |
} |
int |
main (int argc, char **argv) |
{ |
Jbig2Ctx *ctx; |
Jbig2HuffmanTable *tables[5]; |
Jbig2HuffmanState *hs; |
Jbig2WordStream ws; |
bool oob; |
int32_t code; |
ctx = jbig2_ctx_new(NULL, 0, NULL, NULL, NULL); |
tables[0] = NULL; |
tables[1] = jbig2_build_huffman_table (ctx, &jbig2_huffman_params_A); |
tables[2] = jbig2_build_huffman_table (ctx, &jbig2_huffman_params_B); |
tables[3] = NULL; |
tables[4] = jbig2_build_huffman_table (ctx, &jbig2_huffman_params_D); |
ws.get_next_word = test_get_word; |
hs = jbig2_huffman_new (ctx, &ws); |
printf("testing jbig2 huffmann decoding..."); |
printf("\t(should be 8 5 (oob) 8)\n"); |
{ |
int i; |
int sequence_length = sizeof(test_tabindex); |
for (i = 0; i < sequence_length; i++) { |
code = jbig2_huffman_get (hs, tables[test_tabindex[i]], &oob); |
if (oob) printf("(oob) "); |
else printf("%d ", code); |
} |
} |
printf("\n"); |
jbig2_ctx_free(ctx); |
return 0; |
} |
#endif |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_huffman.h |
---|
0,0 → 1,105 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifndef JBIG2_HUFFMAN_H |
#define JBIG2_HUFFMAN_H |
/* Huffman coder interface */ |
typedef struct _Jbig2HuffmanEntry Jbig2HuffmanEntry; |
typedef struct _Jbig2HuffmanState Jbig2HuffmanState; |
typedef struct _Jbig2HuffmanTable Jbig2HuffmanTable; |
typedef struct _Jbig2HuffmanParams Jbig2HuffmanParams; |
struct _Jbig2HuffmanEntry { |
union { |
int32_t RANGELOW; |
Jbig2HuffmanTable *ext_table; |
} u; |
byte PREFLEN; |
byte RANGELEN; |
byte flags; |
}; |
struct _Jbig2HuffmanTable { |
int log_table_size; |
Jbig2HuffmanEntry *entries; |
}; |
typedef struct _Jbig2HuffmanLine Jbig2HuffmanLine; |
struct _Jbig2HuffmanLine { |
int PREFLEN; |
int RANGELEN; |
int RANGELOW; |
}; |
struct _Jbig2HuffmanParams { |
bool HTOOB; |
int n_lines; |
const Jbig2HuffmanLine *lines; |
}; |
Jbig2HuffmanState * |
jbig2_huffman_new (Jbig2Ctx *ctx, Jbig2WordStream *ws); |
void |
jbig2_huffman_free (Jbig2Ctx *ctx, Jbig2HuffmanState *hs); |
void |
jbig2_huffman_skip(Jbig2HuffmanState *hs); |
void jbig2_huffman_advance(Jbig2HuffmanState *hs, int offset); |
int |
jbig2_huffman_offset(Jbig2HuffmanState *hs); |
int32_t |
jbig2_huffman_get (Jbig2HuffmanState *hs, |
const Jbig2HuffmanTable *table, bool *oob); |
int32_t |
jbig2_huffman_get_bits (Jbig2HuffmanState *hs, const int bits); |
#ifdef JBIG2_DEBUG |
void jbig2_dump_huffman_state(Jbig2HuffmanState *hs); |
void jbig2_dump_huffman_binary(Jbig2HuffmanState *hs); |
#endif |
Jbig2HuffmanTable * |
jbig2_build_huffman_table (Jbig2Ctx *ctx, const Jbig2HuffmanParams *params); |
void |
jbig2_release_huffman_table (Jbig2Ctx *ctx, Jbig2HuffmanTable *table); |
/* standard Huffman templates defined by the specification */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_A; /* Table B.1 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_B; /* Table B.2 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_C; /* Table B.3 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_D; /* Table B.4 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_E; /* Table B.5 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_F; /* Table B.6 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_G; /* Table B.7 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_H; /* Table B.8 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_I; /* Table B.9 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_J; /* Table B.10 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_K; /* Table B.11 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_L; /* Table B.12 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_M; /* Table B.13 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_N; /* Table B.14 */ |
extern const Jbig2HuffmanParams jbig2_huffman_params_O; /* Table B.15 */ |
#endif /* JBIG2_HUFFMAN_H */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_hufftab.h |
---|
0,0 → 1,335 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* predefined Huffman table definitions |
-- See Annex B of the JBIG2 specification */ |
#ifndef JBIG2_HUFFTAB_H |
#define JBIG2_HUFFTAB_H |
/* types are in jbig2_huffman.h, you must include that first */ |
/* Table B.1 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_A[] = { |
{ 1, 4, 0 }, |
{ 2, 8, 16 }, |
{ 3, 16, 272 }, |
{ 0, 32, -1 }, /* low */ |
{ 3, 32, 65808 } /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_A = { FALSE, 5, jbig2_huffman_lines_A }; |
/* Table B.2 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_B[] = { |
{ 1, 0, 0 }, |
{ 2, 0, 1 }, |
{ 3, 0, 2 }, |
{ 4, 3, 3 }, |
{ 5, 6, 11 }, |
{ 0, 32, -1 }, /* low */ |
{ 6, 32, 75 }, /* high */ |
{ 6, 0, 0 } |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_B = { TRUE, 8, jbig2_huffman_lines_B }; |
/* Table B.3 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_C[] = { |
{ 8, 8, -256 }, |
{ 1, 0, 0 }, |
{ 2, 0, 1 }, |
{ 3, 0, 2 }, |
{ 4, 3, 3 }, |
{ 5, 6, 11 }, |
{ 8, 32, -257 }, /* low */ |
{ 7, 32, 75 }, /* high */ |
{ 6, 0, 0 } /* OOB */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_C = { TRUE, 9, jbig2_huffman_lines_C }; |
/* Table B.4 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_D[] = { |
{ 1, 0, 1 }, |
{ 2, 0, 2 }, |
{ 3, 0, 3 }, |
{ 4, 3, 4 }, |
{ 5, 6, 12 }, |
{ 0, 32, -1 }, /* low */ |
{ 5, 32, 76 }, /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_D = { FALSE, 7, jbig2_huffman_lines_D }; |
/* Table B.5 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_E[] = { |
{7, 8, -255}, |
{1, 0, 1}, |
{2, 0, 2}, |
{3, 0, 3}, |
{4, 3, 4}, |
{5, 6, 12}, |
{7, 32, -256}, /* low */ |
{6, 32, 76} /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_E = { FALSE, 8, jbig2_huffman_lines_E }; |
/* Table B.6 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_F[] = { |
{5, 10, -2048}, |
{4, 9, -1024}, |
{4, 8, -512}, |
{4, 7, -256}, |
{5, 6, -128}, |
{5, 5, -64}, |
{4, 5, -32}, |
{2, 7, 0}, |
{3, 7, 128}, |
{3, 8, 256}, |
{4, 9, 512}, |
{4, 10, 1024}, |
{6, 32, -2049}, /* low */ |
{6, 32, 2048} /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_F = { FALSE, 14, jbig2_huffman_lines_F }; |
/* Table B.7 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_G[] = { |
{4, 9, -1024}, |
{3, 8, -512}, |
{4, 7, -256}, |
{5, 6, -128}, |
{5, 5, -64}, |
{4, 5, -32}, |
{4, 5, 0}, |
{5, 5, 32}, |
{5, 6, 64}, |
{4, 7, 128}, |
{3, 8, 256}, |
{3, 9, 512}, |
{3, 10, 1024}, |
{5, 32, -1025}, /* low */ |
{5, 32, 2048} /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_G = { FALSE, 15, jbig2_huffman_lines_G }; |
/* Table B.8 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_H[] = { |
{8, 3, -15}, |
{9, 1, -7}, |
{8, 1, -5}, |
{9, 0, -3}, |
{7, 0, -2}, |
{4, 0, -1}, |
{2, 1, 0}, |
{5, 0, 2}, |
{6, 0, 3}, |
{3, 4, 4}, |
{6, 1, 20}, |
{4, 4, 22}, |
{4, 5, 38}, |
{5, 6, 70}, |
{5, 7, 134}, |
{6, 7, 262}, |
{7, 8, 390}, |
{6, 10, 646}, |
{9, 32, -16}, /* low */ |
{9, 32, 1670}, /* high */ |
{2, 0, 0} /* OOB */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_H = { TRUE, 21, jbig2_huffman_lines_H }; |
/* Table B.9 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_I[] = { |
{8, 4, -31}, |
{9, 2, -15}, |
{8, 2, -11}, |
{9, 1, -7}, |
{7, 1, -5}, |
{4, 1, -3}, |
{3, 1, -1}, |
{3, 1, 1}, |
{5, 1, 3}, |
{6, 1, 5}, |
{3, 5, 7}, |
{6, 2, 39}, |
{4, 5, 43}, |
{4, 6, 75}, |
{5, 7, 139}, |
{5, 8, 267}, |
{6, 8, 523}, |
{7, 9, 779}, |
{6, 11, 1291}, |
{9, 32, -32}, /* low */ |
{9, 32, 3339}, /* high */ |
{2, 0, 0} /* OOB */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_I = { TRUE, 22, jbig2_huffman_lines_I }; |
/* Table B.10 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_J[] = { |
{7, 4, -21}, |
{8, 0, -5}, |
{7, 0, -4}, |
{5, 0, -3}, |
{2, 2, -2}, |
{5, 0, 2}, |
{6, 0, 3}, |
{7, 0, 4}, |
{8, 0, 5}, |
{2, 6, 6}, |
{5, 5, 70}, |
{6, 5, 102}, |
{6, 6, 134}, |
{6, 7, 198}, |
{6, 8, 326}, |
{6, 9, 582}, |
{6, 10, 1094}, |
{7, 11, 2118}, |
{8, 32, -22}, /* low */ |
{8, 32, 4166}, /* high */ |
{2, 0, 0} /* OOB */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_J = { TRUE, 21, jbig2_huffman_lines_J }; |
/* Table B.11 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_K[] = { |
{1, 0, 1}, |
{2, 1, 2}, |
{4, 0, 3}, |
{4, 1, 5}, |
{5, 1, 7}, |
{5, 2, 9}, |
{6, 2, 13}, |
{7, 2, 17}, |
{7, 3, 21}, |
{7, 4, 29}, |
{7, 5, 45}, |
{7, 6, 77}, |
{7, 32, 141} /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_K = { FALSE, 13, jbig2_huffman_lines_K }; |
/* Table B.12 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_L[] = { |
{1, 0, 1}, |
{2, 0, 2}, |
{3, 1, 3}, |
{5, 0, 5}, |
{5, 1, 6}, |
{6, 1, 8}, |
{7, 0, 10}, |
{7, 1, 11}, |
{7, 2, 13}, |
{7, 3, 17}, |
{7, 4, 25}, |
{8, 5, 41}, |
{8, 32, 73} |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_L = { FALSE, 13, jbig2_huffman_lines_L }; |
/* Table B.13 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_M[] = { |
{1, 0, 1}, |
{3, 0, 2}, |
{4, 0, 3}, |
{5, 0, 4}, |
{4, 1, 5}, |
{3, 3, 7}, |
{6, 1, 15}, |
{6, 2, 17}, |
{6, 3, 21}, |
{6, 4, 29}, |
{6, 5, 45}, |
{7, 6, 77}, |
{7, 32, 141} /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_M = { FALSE, 13, jbig2_huffman_lines_M }; |
/* Table B.14 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_N[] = { |
{ 3, 0, -2 }, |
{ 3, 0, -1 }, |
{ 1, 0, 0 }, |
{ 3, 3, 1 }, |
{ 3, 6, 2 }, |
{ 0, 32, -1 }, /* low */ |
{ 0, 32, 3 }, /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_N = { FALSE, 7, jbig2_huffman_lines_N }; |
/* Table B.15 */ |
const Jbig2HuffmanLine |
jbig2_huffman_lines_O[] = { |
{7, 4, -24}, |
{6, 2, -8}, |
{5, 1, -4}, |
{4, 0, -2}, |
{3, 0, -1}, |
{1, 0, 0}, |
{3, 0, 1}, |
{4, 0, 2}, |
{5, 1, 3}, |
{6, 2, 5}, |
{7, 4, 9}, |
{7, 32, -25}, /* low */ |
{7, 32, 25} /* high */ |
}; |
const Jbig2HuffmanParams |
jbig2_huffman_params_O = { FALSE, 13, jbig2_huffman_lines_O }; |
#endif /* JBIG2_HUFFTAB_H */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_image.c |
---|
0,0 → 1,313 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> /* memcpy() */ |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_image.h" |
/* allocate a Jbig2Image structure and its associated bitmap */ |
Jbig2Image* jbig2_image_new(Jbig2Ctx *ctx, int width, int height) |
{ |
Jbig2Image *image; |
int stride; |
image = (Jbig2Image *)jbig2_alloc(ctx->allocator, sizeof(*image)); |
if (image == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"could not allocate image structure"); |
return NULL; |
} |
stride = ((width - 1) >> 3) + 1; /* generate a byte-aligned stride */ |
image->data = (uint8_t *)jbig2_alloc(ctx->allocator, stride*height); |
if (image->data == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"could not allocate image data buffer! [%d bytes]\n", stride*height); |
jbig2_free(ctx->allocator, image); |
return NULL; |
} |
image->width = width; |
image->height = height; |
image->stride = stride; |
image->refcount = 1; |
return image; |
} |
/* clone an image pointer by bumping its reference count */ |
Jbig2Image* jbig2_image_clone(Jbig2Ctx *ctx, Jbig2Image *image) |
{ |
image->refcount++; |
return image; |
} |
/* release an image pointer, freeing it it appropriate */ |
void jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image) |
{ |
image->refcount--; |
if (!image->refcount) jbig2_image_free(ctx, image); |
} |
/* free a Jbig2Image structure and its associated memory */ |
void jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image) |
{ |
jbig2_free(ctx->allocator, image->data); |
jbig2_free(ctx->allocator, image); |
} |
/* resize a Jbig2Image */ |
Jbig2Image *jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image, |
int width, int height) |
{ |
if (width == image->width) { |
/* use the same stride, just change the length */ |
image->data = jbig2_realloc(ctx->allocator, |
image->data, image->stride*height); |
if (image->data == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"could not resize image buffer!"); |
return NULL; |
} |
if (height > image->height) { |
memset(image->data + image->height*image->stride, |
0, (height - image->height)*image->stride); |
} |
image->height = height; |
} else { |
/* we must allocate a new image buffer and copy */ |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, |
"jbig2_image_resize called with a different width (NYI)"); |
} |
return NULL; |
} |
/* composite one jbig2_image onto another |
slow but general version */ |
int jbig2_image_compose_unopt(Jbig2Ctx *ctx, |
Jbig2Image *dst, Jbig2Image *src, |
int x, int y, Jbig2ComposeOp op) |
{ |
int i, j; |
int sw = src->width; |
int sh = src->height; |
int sx = 0; |
int sy = 0; |
/* clip to the dst image boundaries */ |
if (x < 0) { sx += -x; sw -= -x; x = 0; } |
if (y < 0) { sy += -y; sh -= -y; y = 0; } |
if (x + sw >= dst->width) sw = dst->width - x; |
if (y + sh >= dst->height) sh = dst->height - y; |
switch (op) { |
case JBIG2_COMPOSE_OR: |
for (j = 0; j < sh; j++) { |
for (i = 0; i < sw; i++) { |
jbig2_image_set_pixel(dst, i+x, j+y, |
jbig2_image_get_pixel(src, i+sx, j+sy) | |
jbig2_image_get_pixel(dst, i+x, j+y)); |
} |
} |
break; |
case JBIG2_COMPOSE_AND: |
for (j = 0; j < sh; j++) { |
for (i = 0; i < sw; i++) { |
jbig2_image_set_pixel(dst, i+x, j+y, |
jbig2_image_get_pixel(src, i+sx, j+sy) & |
jbig2_image_get_pixel(dst, i+x, j+y)); |
} |
} |
break; |
case JBIG2_COMPOSE_XOR: |
for (j = 0; j < sh; j++) { |
for (i = 0; i < sw; i++) { |
jbig2_image_set_pixel(dst, i+x, j+y, |
jbig2_image_get_pixel(src, i+sx, j+sy) ^ |
jbig2_image_get_pixel(dst, i+x, j+y)); |
} |
} |
break; |
case JBIG2_COMPOSE_XNOR: |
for (j = 0; j < sh; j++) { |
for (i = 0; i < sw; i++) { |
jbig2_image_set_pixel(dst, i+x, j+y, |
~(jbig2_image_get_pixel(src, i+sx, j+sy) ^ |
jbig2_image_get_pixel(dst, i+x, j+y))); |
} |
} |
break; |
case JBIG2_COMPOSE_REPLACE: |
for (j = 0; j < sh; j++) { |
for (i = 0; i < sw; i++) { |
jbig2_image_set_pixel(dst, i+x, j+y, |
jbig2_image_get_pixel(src, i+sx, j+sy)); |
} |
} |
break; |
} |
return 0; |
} |
/* composite one jbig2_image onto another */ |
int jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, |
int x, int y, Jbig2ComposeOp op) |
{ |
int i, j; |
int w, h; |
int leftbyte, rightbyte; |
int shift; |
uint8_t *s, *ss; |
uint8_t *d, *dd; |
uint8_t mask, rightmask; |
if (op != JBIG2_COMPOSE_OR) { |
/* hand off the the general routine */ |
return jbig2_image_compose_unopt(ctx, dst, src, x, y, op); |
} |
/* clip */ |
w = src->width; |
h = src->height; |
ss = src->data; |
/* FIXME: this isn't sufficient for the < 0 cases */ |
if (x < 0) { w += x; x = 0; } |
if (y < 0) { h += y; y = 0; } |
w = (x + w < dst->width) ? w : dst->width - x; |
h = (y + h < dst->height) ? h : dst->height - y; |
#ifdef JBIG2_DEBUG |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, |
"compositing %dx%d at (%d, %d) after clipping\n", |
w, h, x, y); |
#endif |
#if 0 |
/* special case complete/strip replacement */ |
/* disabled because it's only safe to do when the destination |
buffer is all-blank. */ |
if ((x == 0) && (w == src->width)) { |
memcpy(dst->data + y*dst->stride, src->data, h*src->stride); |
return 0; |
} |
#endif |
leftbyte = x >> 3; |
rightbyte = (x + w - 1) >> 3; |
shift = x & 7; |
/* general OR case */ |
s = ss; |
d = dd = dst->data + y*dst->stride + leftbyte; |
if (leftbyte == rightbyte) { |
mask = 0x100 - (0x100 >> w); |
for (j = 0; j < h; j++) { |
*d |= (*s & mask) >> shift; |
d += dst->stride; |
s += src->stride; |
} |
} else if (shift == 0) { |
rightmask = (w & 7) ? 0x100 - (1 << (8 - (w & 7))) : 0xFF; |
for (j = 0; j < h; j++) { |
for (i = leftbyte; i < rightbyte; i++) |
*d++ |= *s++; |
*d |= *s & rightmask; |
d = (dd += dst->stride); |
s = (ss += src->stride); |
} |
} else { |
bool overlap = (((w + 7) >> 3) < ((x + w + 7) >> 3) - (x >> 3)); |
mask = 0x100 - (1 << shift); |
if (overlap) |
rightmask = (0x100 - (0x100 >> ((x + w) & 7))) >> (8 - shift); |
else |
rightmask = 0x100 - (0x100 >> (w & 7)); |
for (j = 0; j < h; j++) { |
*d++ |= (*s & mask) >> shift; |
for(i = leftbyte; i < rightbyte - 1; i++) { |
*d |= ((*s++ & ~mask) << (8 - shift)); |
*d++ |= ((*s & mask) >> shift); |
} |
if (overlap) |
*d |= (*s & rightmask) << (8 - shift); |
else |
*d |= ((s[0] & ~mask) << (8 - shift)) | |
((s[1] & rightmask) >> shift); |
d = (dd += dst->stride); |
s = (ss += src->stride); |
} |
} |
return 0; |
} |
/* initialize an image bitmap to a constant value */ |
void jbig2_image_clear(Jbig2Ctx *ctx, Jbig2Image *image, int value) |
{ |
const uint8_t fill = value ? 0xFF : 0x00; |
memset(image->data, fill, image->stride*image->height); |
} |
/* look up a pixel value in an image. |
returns 0 outside the image frame for the convenience of |
the template code |
*/ |
int jbig2_image_get_pixel(Jbig2Image *image, int x, int y) |
{ |
const int w = image->width; |
const int h = image->height; |
const int byte = (x >> 3) + y*image->stride; |
const int bit = 7 - (x & 7); |
if ((x < 0) || (x >= w)) return 0; |
if ((y < 0) || (y >= h)) return 0; |
return ((image->data[byte]>>bit) & 1); |
} |
/* set an individual pixel value in an image */ |
int jbig2_image_set_pixel(Jbig2Image *image, int x, int y, bool value) |
{ |
const int w = image->width; |
const int h = image->height; |
int scratch, mask; |
int bit, byte; |
if ((x < 0) || (x >= w)) return 0; |
if ((y < 0) || (y >= h)) return 0; |
byte = (x >> 3) + y*image->stride; |
bit = 7 - (x & 7); |
mask = (1 << bit) ^ 0xff; |
scratch = image->data[byte] & mask; |
image->data[byte] = scratch | (value << bit); |
return 1; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_image.h |
---|
0,0 → 1,38 |
/* |
jbig2dec |
Copyright (C) 2001-2002 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifndef _JBIG2_IMAGE_H |
#define _JBIG2_IMAGE_H |
int jbig2_image_get_pixel(Jbig2Image *image, int x, int y); |
int jbig2_image_set_pixel(Jbig2Image *image, int x, int y, int value); |
/* routines for dumping the image data in various formats */ |
/* FIXME: should these be in the client instead? */ |
#include <stdio.h> |
int jbig2_image_write_pbm_file(Jbig2Image *image, char *filename); |
int jbig2_image_write_pbm(Jbig2Image *image, FILE *out); |
Jbig2Image *jbig2_image_read_pbm_file(Jbig2Ctx *ctx, char *filename); |
Jbig2Image *jbig2_image_read_pbm(Jbig2Ctx *ctx, FILE *in); |
#ifdef HAVE_LIBPNG |
int jbig2_image_write_png_file(Jbig2Image *image, char *filename); |
int jbig2_image_write_png(Jbig2Image *image, FILE *out); |
#endif |
#endif /* _JBIG2_IMAGE_H */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_image_pbm.c |
---|
0,0 → 1,150 |
/* |
jbig2dec |
Copyright (C) 2009 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stdio.h> |
#include <ctype.h> |
#include "jbig2.h" |
#include "jbig2_image.h" |
/* take an image structure and write it to a file in pbm format */ |
int jbig2_image_write_pbm_file(Jbig2Image *image, char *filename) |
{ |
FILE *out; |
int error; |
if ((out = fopen(filename, "wb")) == NULL) { |
fprintf(stderr, "unable to open '%s' for writing", filename); |
return 1; |
} |
error = jbig2_image_write_pbm(image, out); |
fclose(out); |
return (error); |
} |
/* write out an image struct as a pbm stream to an open file pointer */ |
int jbig2_image_write_pbm(Jbig2Image *image, FILE *out) |
{ |
/* pbm header */ |
fprintf(out, "P4\n%d %d\n", image->width, image->height); |
/* pbm format pads to a byte boundary, so we can |
just write out the whole data buffer |
NB: this assumes minimal stride for the width */ |
fwrite(image->data, 1, image->height*image->stride, out); |
/* success */ |
return 0; |
} |
/* take an image from a file in pbm format */ |
Jbig2Image *jbig2_image_read_pbm_file(Jbig2Ctx *ctx, char *filename) |
{ |
FILE *in; |
Jbig2Image *image; |
if ((in = fopen(filename, "rb")) == NULL) { |
fprintf(stderr, "unable to open '%s' for reading\n", filename); |
return NULL; |
} |
image = jbig2_image_read_pbm(ctx, in); |
fclose(in); |
return (image); |
} |
/* FIXME: should handle multi-image files */ |
Jbig2Image *jbig2_image_read_pbm(Jbig2Ctx *ctx, FILE *in) |
{ |
int i, dim[2]; |
int done; |
Jbig2Image *image; |
int c; |
char buf[32]; |
/* look for 'P4' magic */ |
while ((c = fgetc(in)) != 'P') { |
if (feof(in)) return NULL; |
} |
if ((c = fgetc(in)) != '4') { |
fprintf(stderr, "not a binary pbm file.\n"); |
return NULL; |
} |
/* read size. we must find two decimal numbers representing |
the image dimensions. 'done' will index whether we're |
looking for the width or the height and 'i' will be our |
array index for copying strings into our buffer */ |
done = 0; |
i = 0; |
while (done < 2) { |
c = fgetc(in); |
/* skip whitespace */ |
if (c == ' ' || c == '\t' || c == '\r' || c == '\n') continue; |
/* skip comments */ |
if (c == '#') { |
while ((c = fgetc(in)) != '\n'); |
continue; |
} |
/* report unexpected eof */ |
if (c == EOF) { |
fprintf(stderr, "end-of-file parsing pbm header\n"); |
return NULL; |
} |
if (isdigit(c)) { |
buf[i++] = c; |
while (isdigit(c = fgetc(in))) { |
if (i >= 32) { |
fprintf(stderr, "pbm parsing error\n"); |
return NULL; |
} |
buf[i++] = c; |
} |
buf[i] = '\0'; |
if (sscanf(buf, "%d", &dim[done]) != 1) { |
fprintf(stderr, "couldn't read pbm image dimensions\n"); |
return NULL; |
} |
i = 0; |
done++; |
} |
} |
/* allocate image structure */ |
image = jbig2_image_new(ctx, dim[0], dim[1]); |
if (image == NULL) { |
fprintf(stderr, "could not allocate %dx%d image for pbm file\n", dim[0], dim[1]); |
return NULL; |
} |
/* the pbm data is byte-aligned, so we can |
do a simple block read */ |
fread(image->data, 1, image->height*image->stride, in); |
if (feof(in)) { |
fprintf(stderr, "unexpected end of pbm file.\n"); |
jbig2_image_release(ctx, image); |
return NULL; |
} |
/* success */ |
return image; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_metadata.c |
---|
0,0 → 1,155 |
/* |
jbig2dec |
Copyright (C) 2003 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stdlib.h> |
#include <string.h> |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_metadata.h" |
/* metadata key,value list object */ |
Jbig2Metadata *jbig2_metadata_new(Jbig2Ctx *ctx, Jbig2Encoding encoding) |
{ |
Jbig2Metadata *md = jbig2_alloc(ctx->allocator, sizeof(Jbig2Metadata)); |
if (md != NULL) { |
md->encoding = encoding; |
md->entries = 0; |
md->max_entries = 4; |
md->keys = jbig2_alloc(ctx->allocator, md->max_entries*sizeof(char*)); |
md->values = jbig2_alloc(ctx->allocator, md->max_entries*sizeof(char*)); |
if (md->keys == NULL || md->values == NULL) { |
jbig2_metadata_free(ctx, md); |
md = NULL; |
} |
} |
return md; |
} |
void jbig2_metadata_free(Jbig2Ctx *ctx, Jbig2Metadata *md) |
{ |
int i; |
if (md->keys) { |
/* assume we own the pointers */ |
for (i = 0; i < md->entries; i++) |
jbig2_free(ctx->allocator, md->keys[i]); |
jbig2_free(ctx->allocator, md->keys); |
} |
if (md->values) { |
for (i = 0; i < md->entries; i++) |
jbig2_free(ctx->allocator, md->values[i]); |
jbig2_free(ctx->allocator, md->values); |
} |
jbig2_free(ctx->allocator, md); |
} |
static char *jbig2_strndup(Jbig2Ctx *ctx, const char *c, const int len) |
{ |
char *s = jbig2_alloc(ctx->allocator, len*sizeof(char)); |
if (s == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"unable to duplicate comment string"); |
} else { |
memcpy(s, c, len); |
} |
return s; |
} |
int jbig2_metadata_add(Jbig2Ctx *ctx, Jbig2Metadata *md, |
const char *key, const int key_length, |
const char *value, const int value_length) |
{ |
char **keys, **values; |
/* grow the array if necessary */ |
if (md->entries == md->max_entries) { |
md->max_entries >>= 2; |
keys = jbig2_realloc(ctx->allocator, md->keys, md->max_entries); |
values = jbig2_realloc(ctx->allocator, md->values, md->max_entries); |
if (keys == NULL || values == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, |
"unable to resize metadata structure"); |
return -1; |
} |
md->keys = keys; |
md->values = values; |
} |
/* copy the passed key,value pair */ |
md->keys[md->entries] = jbig2_strndup(ctx, key, key_length); |
md->values[md->entries] = jbig2_strndup(ctx, value, value_length); |
md->entries++; |
return 0; |
} |
/* decode an ascii comment segment 7.4.15.1 */ |
int jbig2_comment_ascii(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data) |
{ |
char *s = (char *)(segment_data + 4); |
char *end = (char *)(segment_data + segment->data_length); |
Jbig2Metadata *comment; |
char *key, *value; |
int key_length, value_length; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"ASCII comment data"); |
comment = jbig2_metadata_new(ctx, JBIG2_ENCODING_ASCII); |
if (comment == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unable to allocate comment structure"); |
return -1; |
} |
/* loop over the segment data pulling out the key,value pairs */ |
while(*s && s < end) { |
key_length = strlen(s) + 1; |
key = s; s += key_length; |
if (s >= end) goto too_short; |
value_length = strlen(s) + 1; |
value = s; s += value_length; |
if (s >= end) goto too_short; |
jbig2_metadata_add(ctx, comment, key, key_length, value, value_length); |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"'%s'\t'%s'", key, value); |
} |
/* TODO: associate with ctx, page, or referred-to segment(s) */ |
segment->result = comment; |
return 0; |
too_short: |
jbig2_metadata_free(ctx, comment); |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unexpected end of comment segment"); |
} |
/* decode a UCS-16 comment segement 7.4.15.2 */ |
int jbig2_comment_unicode(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data) |
{ |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled unicode comment segment"); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_metadata.h |
---|
0,0 → 1,48 |
/* |
jbig2dec |
Copyright (C) 2003 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifndef _JBIG2_METADATA_H |
#define _JBIG2_METADATA_H |
/* metadata from extension segments */ |
/* these bits should be moved to jbig2.h for public access */ |
typedef enum { |
JBIG2_ENCODING_ASCII, |
JBIG2_ENCODING_UCS16 |
} Jbig2Encoding; |
typedef struct _Jbig2Metadata Jbig2Metadata; |
Jbig2Metadata *jbig2_metadata_new(Jbig2Ctx *ctx, Jbig2Encoding encoding); |
void jbig2_metadata_free(Jbig2Ctx *ctx, Jbig2Metadata *md); |
int jbig2_metadata_add(Jbig2Ctx *ctx, Jbig2Metadata *md, |
const char *key, const int key_length, |
const char *value, const int value_length); |
struct _Jbig2Metadata { |
Jbig2Encoding encoding; |
char **keys, **values; |
int entries, max_entries; |
}; |
/* these bits can go to jbig2_priv.h */ |
int jbig2_comment_ascii(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data); |
int jbig2_comment_unicode(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data); |
#endif /* _JBIG2_METADATA_H */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_mmr.c |
---|
0,0 → 1,998 |
/* |
jbig2dec |
Copyright (C) 2001-2002 Artifex Software, Inc. |
This software is provided AS-IS with no warranty, |
either express or implied. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* An implementation of MMR decoding. This is based on the |
implementation in Fitz, which in turn is based on the one |
in Ghostscript. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> |
#include <stdio.h> |
#include <string.h> |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#include "jbig2_generic.h" |
#include "jbig2_mmr.h" |
typedef struct { |
int width; |
int height; |
const byte *data; |
size_t size; |
int data_index; |
int bit_index; |
uint32_t word; |
} Jbig2MmrCtx; |
static void |
jbig2_decode_mmr_init(Jbig2MmrCtx *mmr, int width, int height, const byte *data, size_t size) |
{ |
int i; |
uint32_t word = 0; |
mmr->width = width; |
mmr->height = height; |
mmr->data = data; |
mmr->size = size; |
mmr->data_index = 0; |
mmr->bit_index = 0; |
for (i = 0; i < size && i < 4; i++) |
word |= (data[i] << ((3 - i) << 3)); |
mmr->word = word; |
} |
static void |
jbig2_decode_mmr_consume(Jbig2MmrCtx *mmr, int n_bits) |
{ |
mmr->word <<= n_bits; |
mmr->bit_index += n_bits; |
while (mmr->bit_index >= 8) { |
mmr->bit_index -= 8; |
if (mmr->data_index + 4 < mmr->size) |
mmr->word |= (mmr->data[mmr->data_index + 4] << mmr->bit_index); |
mmr->data_index++; |
} |
} |
/* |
<raph> the first 2^(initialbits) entries map bit patterns to decodes |
<raph> let's say initial_bits is 8 for the sake of example |
<raph> and that the code is 1001 |
<raph> that means that entries 0x90 .. 0x9f have the entry { val, 4 } |
<raph> because those are all the bytes that start with the code |
<raph> and the 4 is the length of the code |
... if (n_bits > initial_bits) ... |
<raph> anyway, in that case, it basically points to a mini table |
<raph> the n_bits is the maximum length of all codes beginning with that byte |
<raph> so 2^(n_bits - initial_bits) is the size of the mini-table |
<raph> peter came up with this, and it makes sense |
*/ |
typedef struct { |
short val; |
short n_bits; |
} mmr_table_node; |
/* white decode table (runlength huffman codes) */ |
const mmr_table_node jbig2_mmr_white_decode[] = { |
{ 256, 12 }, |
{ 272, 12 }, |
{ 29, 8 }, |
{ 30, 8 }, |
{ 45, 8 }, |
{ 46, 8 }, |
{ 22, 7 }, |
{ 22, 7 }, |
{ 23, 7 }, |
{ 23, 7 }, |
{ 47, 8 }, |
{ 48, 8 }, |
{ 13, 6 }, |
{ 13, 6 }, |
{ 13, 6 }, |
{ 13, 6 }, |
{ 20, 7 }, |
{ 20, 7 }, |
{ 33, 8 }, |
{ 34, 8 }, |
{ 35, 8 }, |
{ 36, 8 }, |
{ 37, 8 }, |
{ 38, 8 }, |
{ 19, 7 }, |
{ 19, 7 }, |
{ 31, 8 }, |
{ 32, 8 }, |
{ 1, 6 }, |
{ 1, 6 }, |
{ 1, 6 }, |
{ 1, 6 }, |
{ 12, 6 }, |
{ 12, 6 }, |
{ 12, 6 }, |
{ 12, 6 }, |
{ 53, 8 }, |
{ 54, 8 }, |
{ 26, 7 }, |
{ 26, 7 }, |
{ 39, 8 }, |
{ 40, 8 }, |
{ 41, 8 }, |
{ 42, 8 }, |
{ 43, 8 }, |
{ 44, 8 }, |
{ 21, 7 }, |
{ 21, 7 }, |
{ 28, 7 }, |
{ 28, 7 }, |
{ 61, 8 }, |
{ 62, 8 }, |
{ 63, 8 }, |
{ 0, 8 }, |
{ 320, 8 }, |
{ 384, 8 }, |
{ 10, 5 }, |
{ 10, 5 }, |
{ 10, 5 }, |
{ 10, 5 }, |
{ 10, 5 }, |
{ 10, 5 }, |
{ 10, 5 }, |
{ 10, 5 }, |
{ 11, 5 }, |
{ 11, 5 }, |
{ 11, 5 }, |
{ 11, 5 }, |
{ 11, 5 }, |
{ 11, 5 }, |
{ 11, 5 }, |
{ 11, 5 }, |
{ 27, 7 }, |
{ 27, 7 }, |
{ 59, 8 }, |
{ 60, 8 }, |
{ 288, 9 }, |
{ 290, 9 }, |
{ 18, 7 }, |
{ 18, 7 }, |
{ 24, 7 }, |
{ 24, 7 }, |
{ 49, 8 }, |
{ 50, 8 }, |
{ 51, 8 }, |
{ 52, 8 }, |
{ 25, 7 }, |
{ 25, 7 }, |
{ 55, 8 }, |
{ 56, 8 }, |
{ 57, 8 }, |
{ 58, 8 }, |
{ 192, 6 }, |
{ 192, 6 }, |
{ 192, 6 }, |
{ 192, 6 }, |
{ 1664, 6 }, |
{ 1664, 6 }, |
{ 1664, 6 }, |
{ 1664, 6 }, |
{ 448, 8 }, |
{ 512, 8 }, |
{ 292, 9 }, |
{ 640, 8 }, |
{ 576, 8 }, |
{ 294, 9 }, |
{ 296, 9 }, |
{ 298, 9 }, |
{ 300, 9 }, |
{ 302, 9 }, |
{ 256, 7 }, |
{ 256, 7 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 2, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 3, 4 }, |
{ 128, 5 }, |
{ 128, 5 }, |
{ 128, 5 }, |
{ 128, 5 }, |
{ 128, 5 }, |
{ 128, 5 }, |
{ 128, 5 }, |
{ 128, 5 }, |
{ 8, 5 }, |
{ 8, 5 }, |
{ 8, 5 }, |
{ 8, 5 }, |
{ 8, 5 }, |
{ 8, 5 }, |
{ 8, 5 }, |
{ 8, 5 }, |
{ 9, 5 }, |
{ 9, 5 }, |
{ 9, 5 }, |
{ 9, 5 }, |
{ 9, 5 }, |
{ 9, 5 }, |
{ 9, 5 }, |
{ 9, 5 }, |
{ 16, 6 }, |
{ 16, 6 }, |
{ 16, 6 }, |
{ 16, 6 }, |
{ 17, 6 }, |
{ 17, 6 }, |
{ 17, 6 }, |
{ 17, 6 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 4, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 14, 6 }, |
{ 14, 6 }, |
{ 14, 6 }, |
{ 14, 6 }, |
{ 15, 6 }, |
{ 15, 6 }, |
{ 15, 6 }, |
{ 15, 6 }, |
{ 64, 5 }, |
{ 64, 5 }, |
{ 64, 5 }, |
{ 64, 5 }, |
{ 64, 5 }, |
{ 64, 5 }, |
{ 64, 5 }, |
{ 64, 5 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ 7, 4 }, |
{ -2, 3 }, |
{ -2, 3 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -3, 4 }, |
{ 1792, 3 }, |
{ 1792, 3 }, |
{ 1984, 4 }, |
{ 2048, 4 }, |
{ 2112, 4 }, |
{ 2176, 4 }, |
{ 2240, 4 }, |
{ 2304, 4 }, |
{ 1856, 3 }, |
{ 1856, 3 }, |
{ 1920, 3 }, |
{ 1920, 3 }, |
{ 2368, 4 }, |
{ 2432, 4 }, |
{ 2496, 4 }, |
{ 2560, 4 }, |
{ 1472, 1 }, |
{ 1536, 1 }, |
{ 1600, 1 }, |
{ 1728, 1 }, |
{ 704, 1 }, |
{ 768, 1 }, |
{ 832, 1 }, |
{ 896, 1 }, |
{ 960, 1 }, |
{ 1024, 1 }, |
{ 1088, 1 }, |
{ 1152, 1 }, |
{ 1216, 1 }, |
{ 1280, 1 }, |
{ 1344, 1 }, |
{ 1408, 1 } |
}; |
/* black decode table (runlength huffman codes) */ |
const mmr_table_node jbig2_mmr_black_decode[] = { |
{ 128, 12 }, |
{ 160, 13 }, |
{ 224, 12 }, |
{ 256, 12 }, |
{ 10, 7 }, |
{ 11, 7 }, |
{ 288, 12 }, |
{ 12, 7 }, |
{ 9, 6 }, |
{ 9, 6 }, |
{ 8, 6 }, |
{ 8, 6 }, |
{ 7, 5 }, |
{ 7, 5 }, |
{ 7, 5 }, |
{ 7, 5 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 6, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 5, 4 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 1, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 4, 3 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 3, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ 2, 2 }, |
{ -2, 4 }, |
{ -2, 4 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -1, 0 }, |
{ -3, 5 }, |
{ 1792, 4 }, |
{ 1792, 4 }, |
{ 1984, 5 }, |
{ 2048, 5 }, |
{ 2112, 5 }, |
{ 2176, 5 }, |
{ 2240, 5 }, |
{ 2304, 5 }, |
{ 1856, 4 }, |
{ 1856, 4 }, |
{ 1920, 4 }, |
{ 1920, 4 }, |
{ 2368, 5 }, |
{ 2432, 5 }, |
{ 2496, 5 }, |
{ 2560, 5 }, |
{ 18, 3 }, |
{ 18, 3 }, |
{ 18, 3 }, |
{ 18, 3 }, |
{ 18, 3 }, |
{ 18, 3 }, |
{ 18, 3 }, |
{ 18, 3 }, |
{ 52, 5 }, |
{ 52, 5 }, |
{ 640, 6 }, |
{ 704, 6 }, |
{ 768, 6 }, |
{ 832, 6 }, |
{ 55, 5 }, |
{ 55, 5 }, |
{ 56, 5 }, |
{ 56, 5 }, |
{ 1280, 6 }, |
{ 1344, 6 }, |
{ 1408, 6 }, |
{ 1472, 6 }, |
{ 59, 5 }, |
{ 59, 5 }, |
{ 60, 5 }, |
{ 60, 5 }, |
{ 1536, 6 }, |
{ 1600, 6 }, |
{ 24, 4 }, |
{ 24, 4 }, |
{ 24, 4 }, |
{ 24, 4 }, |
{ 25, 4 }, |
{ 25, 4 }, |
{ 25, 4 }, |
{ 25, 4 }, |
{ 1664, 6 }, |
{ 1728, 6 }, |
{ 320, 5 }, |
{ 320, 5 }, |
{ 384, 5 }, |
{ 384, 5 }, |
{ 448, 5 }, |
{ 448, 5 }, |
{ 512, 6 }, |
{ 576, 6 }, |
{ 53, 5 }, |
{ 53, 5 }, |
{ 54, 5 }, |
{ 54, 5 }, |
{ 896, 6 }, |
{ 960, 6 }, |
{ 1024, 6 }, |
{ 1088, 6 }, |
{ 1152, 6 }, |
{ 1216, 6 }, |
{ 64, 3 }, |
{ 64, 3 }, |
{ 64, 3 }, |
{ 64, 3 }, |
{ 64, 3 }, |
{ 64, 3 }, |
{ 64, 3 }, |
{ 64, 3 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 13, 1 }, |
{ 23, 4 }, |
{ 23, 4 }, |
{ 50, 5 }, |
{ 51, 5 }, |
{ 44, 5 }, |
{ 45, 5 }, |
{ 46, 5 }, |
{ 47, 5 }, |
{ 57, 5 }, |
{ 58, 5 }, |
{ 61, 5 }, |
{ 256, 5 }, |
{ 16, 3 }, |
{ 16, 3 }, |
{ 16, 3 }, |
{ 16, 3 }, |
{ 17, 3 }, |
{ 17, 3 }, |
{ 17, 3 }, |
{ 17, 3 }, |
{ 48, 5 }, |
{ 49, 5 }, |
{ 62, 5 }, |
{ 63, 5 }, |
{ 30, 5 }, |
{ 31, 5 }, |
{ 32, 5 }, |
{ 33, 5 }, |
{ 40, 5 }, |
{ 41, 5 }, |
{ 22, 4 }, |
{ 22, 4 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 14, 1 }, |
{ 15, 2 }, |
{ 15, 2 }, |
{ 15, 2 }, |
{ 15, 2 }, |
{ 15, 2 }, |
{ 15, 2 }, |
{ 15, 2 }, |
{ 15, 2 }, |
{ 128, 5 }, |
{ 192, 5 }, |
{ 26, 5 }, |
{ 27, 5 }, |
{ 28, 5 }, |
{ 29, 5 }, |
{ 19, 4 }, |
{ 19, 4 }, |
{ 20, 4 }, |
{ 20, 4 }, |
{ 34, 5 }, |
{ 35, 5 }, |
{ 36, 5 }, |
{ 37, 5 }, |
{ 38, 5 }, |
{ 39, 5 }, |
{ 21, 4 }, |
{ 21, 4 }, |
{ 42, 5 }, |
{ 43, 5 }, |
{ 0, 3 }, |
{ 0, 3 }, |
{ 0, 3 }, |
{ 0, 3 } |
}; |
#define getbit(buf, x) ( ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 ) |
static int |
jbig2_find_changing_element(const byte *line, int x, int w) |
{ |
int a, b; |
if (line == 0) |
return w; |
if (x == -1) { |
a = 0; |
x = 0; |
} |
else { |
a = getbit(line, x); |
x ++; |
} |
while (x < w) { |
b = getbit(line, x); |
if (a != b) |
break; |
x++; |
} |
return x; |
} |
static int |
jbig2_find_changing_element_of_color(const byte *line, int x, int w, int color) |
{ |
if (line == 0) |
return w; |
x = jbig2_find_changing_element(line, x, w); |
if (x < w && getbit(line, x) != color) |
x = jbig2_find_changing_element(line, x, w); |
return x; |
} |
static const byte lm[8] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 }; |
static const byte rm[8] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE }; |
static void |
jbig2_set_bits(byte *line, int x0, int x1) |
{ |
int a0, a1, b0, b1, a; |
a0 = x0 >> 3; |
a1 = x1 >> 3; |
b0 = x0 & 7; |
b1 = x1 & 7; |
if (a0 == a1) { |
line[a0] |= lm[b0] & rm[b1]; |
} |
else { |
line[a0] |= lm[b0]; |
for (a = a0 + 1; a < a1; a++) |
line[a] = 0xFF; |
line[a1] |= rm[b1]; |
} |
} |
static int |
jbig2_decode_get_code(Jbig2MmrCtx *mmr, const mmr_table_node *table, int initial_bits) |
{ |
uint32_t word = mmr->word; |
int table_ix = word >> (32 - initial_bits); |
int val = table[table_ix].val; |
int n_bits = table[table_ix].n_bits; |
if (n_bits > initial_bits) { |
int mask = (1 << (32 - initial_bits)) - 1; |
table_ix = val + ((word & mask) >> (32 - n_bits)); |
val = table[table_ix].val; |
n_bits = initial_bits + table[table_ix].n_bits; |
} |
jbig2_decode_mmr_consume(mmr, n_bits); |
return val; |
} |
static int |
jbig2_decode_get_run(Jbig2MmrCtx *mmr, const mmr_table_node *table, int initial_bits) |
{ |
int result = 0; |
int val; |
do { |
val = jbig2_decode_get_code(mmr, table, initial_bits); |
result += val; |
} while (val >= 64); |
return result; |
} |
static void |
jbig2_decode_mmr_line(Jbig2MmrCtx *mmr, const byte *ref, byte *dst) |
{ |
int a0, a1, a2, b1, b2; |
int c; |
a0 = -1; |
c = 0; /* 0 is white, black is 1 */ |
while (1) |
{ |
uint32_t word = mmr->word; |
/* printf ("%08x\n", word); */ |
if (a0 >= mmr->width) |
break; |
if ((word >> (32 - 3)) == 1) |
{ |
int white_run, black_run; |
jbig2_decode_mmr_consume(mmr, 3); |
if (a0 == -1) |
a0 = 0; |
if (c == 0) { |
white_run = jbig2_decode_get_run(mmr, jbig2_mmr_white_decode, 8); |
black_run = jbig2_decode_get_run(mmr, jbig2_mmr_black_decode, 7); |
a1 = a0 + white_run; |
a2 = a1 + black_run; |
if (a1 > mmr->width) a1 = mmr->width; |
if (a2 > mmr->width) a2 = mmr->width; |
jbig2_set_bits(dst, a1, a2); |
a0 = a2; |
/* printf ("H %d %d\n", white_run, black_run); */ |
} |
else |
{ |
black_run = jbig2_decode_get_run(mmr, jbig2_mmr_black_decode, 7); |
white_run = jbig2_decode_get_run(mmr, jbig2_mmr_white_decode, 8); |
a1 = a0 + black_run; |
a2 = a1 + white_run; |
if (a1 > mmr->width) a1 = mmr->width; |
if (a2 > mmr->width) a2 = mmr->width; |
jbig2_set_bits(dst, a0, a1); |
a0 = a2; |
/* printf ("H %d %d\n", black_run, white_run); */ |
} |
} |
else if ((word >> (32 - 4)) == 1) |
{ |
/* printf ("P\n"); */ |
jbig2_decode_mmr_consume(mmr, 4); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
b2 = jbig2_find_changing_element(ref, b1, mmr->width); |
if (c) jbig2_set_bits(dst, a0, b2); |
a0 = b2; |
} |
else if ((word >> (32 - 1)) == 1) |
{ |
/* printf ("V(0)\n"); */ |
jbig2_decode_mmr_consume(mmr, 1); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
if (c) jbig2_set_bits(dst, a0, b1); |
a0 = b1; |
c = !c; |
} |
else if ((word >> (32 - 3)) == 3) |
{ |
/* printf ("VR(1)\n"); */ |
jbig2_decode_mmr_consume(mmr, 3); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
if (b1 + 1 > mmr->width) break; |
if (c) jbig2_set_bits(dst, a0, b1 + 1); |
a0 = b1 + 1; |
c = !c; |
} |
else if ((word >> (32 - 6)) == 3) |
{ |
/* printf ("VR(2)\n"); */ |
jbig2_decode_mmr_consume(mmr, 6); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
if (b1 + 2 > mmr->width) break; |
if (c) jbig2_set_bits(dst, a0, b1 + 2); |
a0 = b1 + 2; |
c = !c; |
} |
else if ((word >> (32 - 7)) == 3) |
{ |
/* printf ("VR(3)\n"); */ |
jbig2_decode_mmr_consume(mmr, 7); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
if (b1 + 3 > mmr->width) break; |
if (c) jbig2_set_bits(dst, a0, b1 + 3); |
a0 = b1 + 3; |
c = !c; |
} |
else if ((word >> (32 - 3)) == 2) |
{ |
/* printf ("VL(1)\n"); */ |
jbig2_decode_mmr_consume(mmr, 3); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
if (b1 - 1 < 0) break; |
if (c) jbig2_set_bits(dst, a0, b1 - 1); |
a0 = b1 - 1; |
c = !c; |
} |
else if ((word >> (32 - 6)) == 2) |
{ |
/* printf ("VL(2)\n"); */ |
jbig2_decode_mmr_consume(mmr, 6); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
if (b1 - 2 < 0) break; |
if (c) jbig2_set_bits(dst, a0, b1 - 2); |
a0 = b1 - 2; |
c = !c; |
} |
else if ((word >> (32 - 7)) == 2) |
{ |
/* printf ("VL(3)\n"); */ |
jbig2_decode_mmr_consume(mmr, 7); |
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c); |
if (b1 - 3 < 0) break; |
if (c) jbig2_set_bits(dst, a0, b1 - 3); |
a0 = b1 - 3; |
c = !c; |
} |
else |
break; |
} |
} |
int |
jbig2_decode_generic_mmr(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
const byte *data, size_t size, |
Jbig2Image *image) |
{ |
Jbig2MmrCtx mmr; |
const int rowstride = image->stride; |
byte *dst = image->data; |
byte *ref = NULL; |
int y; |
jbig2_decode_mmr_init(&mmr, image->width, image->height, data, size); |
for (y = 0; y < image->height; y++) { |
memset(dst, 0, rowstride); |
jbig2_decode_mmr_line(&mmr, ref, dst); |
ref = dst; |
dst += rowstride; |
} |
return 0; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_mmr.h |
---|
0,0 → 1,22 |
/* |
jbig2dec |
Copyright (C) 2001 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
int |
jbig2_decode_generic_mmr(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2GenericRegionParams *params, |
const byte *data, size_t size, |
Jbig2Image *image); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_page.c |
---|
0,0 → 1,327 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stdlib.h> |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#ifdef OUTPUT_PBM |
#include <stdio.h> |
#include "jbig2_image.h" |
#endif |
/* dump the page struct info */ |
static void |
dump_page_info(Jbig2Ctx *ctx, Jbig2Segment *segment, Jbig2Page *page) |
{ |
if (page->x_resolution == 0) { |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"page %d image is %dx%d (unknown res)", page->number, |
page->width, page->height); |
} else if (page->x_resolution == page->y_resolution) { |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"page %d image is %dx%d (%d ppm)", page->number, |
page->width, page->height, |
page->x_resolution); |
} else { |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"page %d image is %dx%d (%dx%d ppm)", page->number, |
page->width, page->height, |
page->x_resolution, page->y_resolution); |
} |
if (page->striped) { |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"\tmaximum stripe size: %d", page->stripe_size); |
} |
} |
/** |
* jbig2_page_info: parse page info segment |
* |
* Parse the page info segment data and fill out a corresponding |
* Jbig2Page struct and ready it for subsequent rendered data, |
* including allocating an image buffer for the page (or the first stripe) |
**/ |
int |
jbig2_page_info (Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data) |
{ |
Jbig2Page *page; |
/* a new page info segment implies the previous page is finished */ |
page = &(ctx->pages[ctx->current_page]); |
if ((page->number != 0) && |
((page->state == JBIG2_PAGE_NEW) || (page->state == JBIG2_PAGE_FREE))) { |
page->state = JBIG2_PAGE_COMPLETE; |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unexpected page info segment, marking previous page finished"); |
} |
/* find a free page */ |
{ |
int index, j; |
index = ctx->current_page; |
while (ctx->pages[index].state != JBIG2_PAGE_FREE) { |
index++; |
if (index >= ctx->max_page_index) { |
/* grow the list */ |
ctx->pages = jbig2_realloc(ctx->allocator, ctx->pages, |
(ctx->max_page_index <<= 2) * sizeof(Jbig2Page)); |
for (j=index; j < ctx->max_page_index; j++) { |
ctx->pages[j].state = JBIG2_PAGE_FREE; |
ctx->pages[j].number = 0; |
ctx->pages[j].image = NULL; |
} |
} |
} |
page = &(ctx->pages[index]); |
ctx->current_page = index; |
page->state = JBIG2_PAGE_NEW; |
page->number = segment->page_association; |
} |
/* FIXME: would be nice if we tried to work around this */ |
if (segment->data_length < 19) { |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"segment too short"); |
} |
/* 7.4.8.x */ |
page->width = jbig2_get_int32(segment_data); |
page->height = jbig2_get_int32(segment_data + 4); |
page->x_resolution = jbig2_get_int32(segment_data + 8); |
page->y_resolution = jbig2_get_int32(segment_data + 12); |
page->flags = segment_data[16]; |
/* 7.4.8.6 */ |
{ |
int16_t striping = jbig2_get_int16(segment_data +17); |
if (striping & 0x8000) { |
page->striped = TRUE; |
page->stripe_size = striping & 0x7FFF; |
} else { |
page->striped = FALSE; |
page->stripe_size = 0; /* would page->height be better? */ |
} |
} |
if (page->height == 0xFFFFFFFF && page->striped == FALSE) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"height is unspecified but page is not markes as striped"); |
page->striped = TRUE; |
} |
page->end_row = 0; |
if (segment->data_length > 19) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"extra data in segment"); |
} |
dump_page_info(ctx, segment, page); |
/* allocate an approprate page image buffer */ |
/* 7.4.8.2 */ |
if (page->height == 0xFFFFFFFF) { |
page->image = jbig2_image_new(ctx, page->width, page->stripe_size); |
} else { |
page->image = jbig2_image_new(ctx, page->width, page->height); |
} |
if (page->image == NULL) { |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"failed to allocate buffer for page image"); |
} else { |
/* 8.2 (3) fill the page with the default pixel value */ |
jbig2_image_clear(ctx, page->image, (page->flags & 4)); |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"allocated %dx%d page image (%d bytes)", |
page->image->width, page->image->height, |
page->image->stride*page->image->height); |
} |
return 0; |
} |
/** |
* jbig2_end_of_stripe: parse and implement an end of stripe segment |
**/ |
int |
jbig2_end_of_stripe(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data) |
{ |
Jbig2Page page = ctx->pages[ctx->current_page]; |
int end_row; |
end_row = jbig2_get_int32(segment_data); |
if (end_row < page.end_row) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"end of stripe segment with non-positive end row advance" |
" (new end row %d vs current end row %d)", |
end_row, page.end_row); |
} else { |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"end of stripe: advancing end row to %d", end_row); |
} |
page.end_row = end_row; |
return 0; |
} |
/** |
* jbig2_complete_page: complete a page image |
* |
* called upon seeing an 'end of page' segment, this routine |
* marks a page as completed so it can be returned. |
* compositing will have already happened in the previous |
* segment handlers. |
**/ |
int |
jbig2_complete_page (Jbig2Ctx *ctx) |
{ |
/* check for unfinished segments */ |
if (ctx->segment_index != ctx->n_segments) { |
Jbig2Segment *segment = ctx->segments[ctx->segment_index]; |
int code = 0; |
/* Some versions of Xerox Workcentre generate PDF files |
with the segment data length field of the last segment |
set to -1. Try to cope with this here. */ |
if ((segment->data_length & 0xffffffff) == 0xffffffff) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"File has an invalid segment data length!" |
" Trying to decode using the available data."); |
segment->data_length = ctx->buf_wr_ix - ctx->buf_rd_ix; |
code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix); |
ctx->buf_rd_ix += segment->data_length; |
ctx->segment_index++; |
} |
} |
ctx->pages[ctx->current_page].state = JBIG2_PAGE_COMPLETE; |
return 0; |
} |
/** |
* jbig2_end_of_page: parse and implement an end of page segment |
**/ |
int |
jbig2_end_of_page(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data) |
{ |
uint32_t page_number = ctx->pages[ctx->current_page].number; |
if (segment->page_association != page_number) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"end of page marker for page %d doesn't match current page number %d", |
segment->page_association, page_number); |
} |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"end of page %d", page_number); |
jbig2_complete_page(ctx); |
#ifdef OUTPUT_PBM |
jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout); |
#endif |
return 0; |
} |
/** |
* jbig2_add_page_result: composite a decoding result onto a page |
* |
* this is called to add the results of segment decode (when it |
* is an image) to a page image buffer |
**/ |
int |
jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *image, |
int x, int y, Jbig2ComposeOp op) |
{ |
/* grow the page to accomodate a new stripe if necessary */ |
if (page->striped) { |
int new_height = y + image->height + page->end_row; |
if (page->image->height < new_height) { |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, |
"growing page buffer to %d rows " |
"to accomodate new stripe", new_height); |
jbig2_image_resize(ctx, page->image, |
page->image->width, new_height); |
} |
} |
jbig2_image_compose(ctx, page->image, image, |
x, y + page->end_row, JBIG2_COMPOSE_OR); |
return 0; |
} |
/** |
* jbig2_get_page: return the next available page image buffer |
* |
* the client can call this at any time to check if any pages |
* have been decoded. If so, it returns the first available |
* one. The client should then call jbig2_release_page() when |
* it no longer needs to refer to the image buffer. |
* |
* since this is a public routine for the library clients, we |
* return an image structure pointer, even though the function |
* name refers to a page; the page structure is private. |
**/ |
Jbig2Image *jbig2_page_out(Jbig2Ctx *ctx) |
{ |
int index; |
/* search for a completed page */ |
for (index=0; index < ctx->max_page_index; index++) { |
if (ctx->pages[index].state == JBIG2_PAGE_COMPLETE) { |
ctx->pages[index].state = JBIG2_PAGE_RETURNED; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, |
"page %d returned to the client", ctx->pages[index].number); |
return jbig2_image_clone(ctx, ctx->pages[index].image); |
} |
} |
/* no pages available */ |
return NULL; |
} |
/** |
* jbig2_release_page: tell the library a page can be freed |
**/ |
int jbig2_release_page(Jbig2Ctx *ctx, Jbig2Image *image) |
{ |
int index; |
/* find the matching page struct and mark it released */ |
for (index = 0; index < ctx->max_page_index; index++) { |
if (ctx->pages[index].image == image) { |
jbig2_image_release(ctx, image); |
ctx->pages[index].state = JBIG2_PAGE_RELEASED; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, |
"page %d released by the client", ctx->pages[index].number); |
return 0; |
} |
} |
/* no matching pages */ |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, |
"jbig2_release_page called on unknown page"); |
return 1; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_priv.h |
---|
0,0 → 1,177 |
/* |
jbig2dec |
Copyright (C) 2002 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* library internals */ |
typedef uint8_t byte; |
typedef int bool; |
#ifndef TRUE |
#define TRUE 1 |
#endif |
#ifndef FALSE |
#define FALSE 0 |
#endif |
#ifndef NULL |
#define NULL ((void*)0) |
#endif |
typedef enum { |
JBIG2_FILE_HEADER, |
JBIG2_FILE_SEQUENTIAL_HEADER, |
JBIG2_FILE_SEQUENTIAL_BODY, |
JBIG2_FILE_RANDOM_HEADERS, |
JBIG2_FILE_RANDOM_BODIES, |
JBIG2_FILE_EOF |
} Jbig2FileState; |
struct _Jbig2Ctx { |
Jbig2Allocator *allocator; |
Jbig2Options options; |
const Jbig2Ctx *global_ctx; |
Jbig2ErrorCallback error_callback; |
void *error_callback_data; |
byte *buf; |
size_t buf_size; |
unsigned int buf_rd_ix; |
unsigned int buf_wr_ix; |
Jbig2FileState state; |
uint8_t file_header_flags; |
int32_t n_pages; |
int n_segments_max; |
Jbig2Segment **segments; |
int n_segments; /* index of last segment header parsed */ |
int segment_index; /* index of last segment body parsed */ |
/* list of decoded pages, including the one in progress, |
currently stored as a contiguous, 0-indexed array. */ |
int current_page; |
int max_page_index; |
Jbig2Page *pages; |
}; |
int32_t |
jbig2_get_int32 (const byte *buf); |
int16_t |
jbig2_get_int16 (const byte *buf); |
/* dynamic memory management */ |
void * |
jbig2_alloc (Jbig2Allocator *allocator, size_t size); |
void |
jbig2_free (Jbig2Allocator *allocator, void *p); |
void * |
jbig2_realloc (Jbig2Allocator *allocator, void *p, size_t size); |
#define jbig2_new(ctx, t, size) ((t *)jbig2_alloc(ctx->allocator, (size) * sizeof(t))) |
#define jbig2_renew(ctx, p, t, size) ((t *)jbig2_realloc(ctx->allocator, (p), (size) * sizeof(t))) |
int |
jbig2_error (Jbig2Ctx *ctx, Jbig2Severity severity, int32_t seg_idx, |
const char *fmt, ...); |
/* the page structure handles decoded page |
results. it's allocated by a 'page info' |
segement and marked complete by an 'end of page' |
segment. |
*/ |
typedef enum { |
JBIG2_PAGE_FREE, |
JBIG2_PAGE_NEW, |
JBIG2_PAGE_COMPLETE, |
JBIG2_PAGE_RETURNED, |
JBIG2_PAGE_RELEASED |
} Jbig2PageState; |
struct _Jbig2Page { |
Jbig2PageState state; |
uint32_t number; |
uint32_t height, width; /* in pixels */ |
uint32_t x_resolution, |
y_resolution; /* in pixels per meter */ |
uint16_t stripe_size; |
bool striped; |
int end_row; |
uint8_t flags; |
Jbig2Image *image; |
}; |
int jbig2_page_info (Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data); |
int jbig2_end_of_stripe(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data); |
int jbig2_end_of_page(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data); |
int jbig2_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data); |
typedef enum { |
JBIG2_COMPOSE_OR = 0, |
JBIG2_COMPOSE_AND = 1, |
JBIG2_COMPOSE_XOR = 2, |
JBIG2_COMPOSE_XNOR = 3, |
JBIG2_COMPOSE_REPLACE = 4 |
} Jbig2ComposeOp; |
int jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, int x, int y, Jbig2ComposeOp op); |
int jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *src, int x, int y, Jbig2ComposeOp op); |
/* region segment info */ |
typedef struct { |
int32_t width; |
int32_t height; |
int32_t x; |
int32_t y; |
Jbig2ComposeOp op; |
uint8_t flags; |
} Jbig2RegionSegmentInfo; |
void jbig2_get_region_segment_info(Jbig2RegionSegmentInfo *info, const uint8_t *segment_data); |
int jbig2_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data); |
/* 7.4 */ |
int jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data); |
int jbig2_refinement_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data); |
int jbig2_pattern_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data); |
int jbig2_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data); |
/* The word stream design is a compromise between simplicity and |
trying to amortize the number of method calls. Each ::get_next_word |
invocation pulls 4 bytes from the stream, packed big-endian into a |
32 bit word. The offset argument is provided as a convenience. It |
begins at 0 and increments by 4 for each successive invocation. */ |
typedef struct _Jbig2WordStream Jbig2WordStream; |
struct _Jbig2WordStream { |
uint32_t (*get_next_word) (Jbig2WordStream *self, int offset); |
}; |
Jbig2WordStream * |
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size); |
void |
jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_refinement.c |
---|
0,0 → 1,440 |
/* |
jbig2dec |
Copyright (C) 2004 Artifex Software, Inc. |
This software is provided AS-IS with no warranty, |
either express or implied. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/** |
* Generic Refinement region handlers. |
**/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> |
#include <string.h> /* memcpy(), memset() */ |
#include <stdio.h> |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#include "jbig2_generic.h" |
#include "jbig2_image.h" |
static int |
jbig2_decode_refinement_template0(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2RefinementRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GR_stats) |
{ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"refinement region template 0 NYI"); |
} |
static int |
jbig2_decode_refinement_template0_unopt(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2RefinementRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GR_stats) |
{ |
const int GRW = image->width; |
const int GRH = image->height; |
const int dx = params->DX; |
const int dy = params->DY; |
Jbig2Image *ref = params->reference; |
uint32_t CONTEXT; |
int x,y; |
bool bit; |
for (y = 0; y < GRH; y++) { |
for (x = 0; x < GRW; x++) { |
CONTEXT = 0; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], |
y + params->grat[1]) << 3; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+1, y-dy+1) << 4; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+0, y-dy+1) << 5; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx-1, y-dy+1) << 6; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+1, y-dy+0) << 7; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+0, y-dy+0) << 8; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx-1, y-dy+0) << 9; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+1, y-dy-1) << 10; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+0, y-dy-1) << 11; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+params->grat[2], |
y-dy+params->grat[3]) << 12; |
bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} |
#ifdef JBIG2_DEBUG_DUMP |
{ |
static count = 0; |
char name[32]; |
snprintf(name, 32, "refin-%d.pbm", count); |
jbig2_image_write_pbm_file(ref, name); |
snprintf(name, 32, "refout-%d.pbm", count); |
jbig2_image_write_pbm_file(image, name); |
count++; |
} |
#endif |
return 0; |
} |
static int |
jbig2_decode_refinement_template1_unopt(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2RefinementRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GR_stats) |
{ |
const int GRW = image->width; |
const int GRH = image->height; |
const int dx = params->DX; |
const int dy = params->DY; |
Jbig2Image *ref = params->reference; |
uint32_t CONTEXT; |
int x,y; |
bool bit; |
for (y = 0; y < GRH; y++) { |
for (x = 0; x < GRW; x++) { |
CONTEXT = 0; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0; |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1; |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2; |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+1, y-dy+1) << 4; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+0, y-dy+1) << 5; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+1, y-dy+0) << 6; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+0, y-dy+0) << 7; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx-1, y-dy+0) << 8; |
CONTEXT |= jbig2_image_get_pixel(ref, x-dx+0, y-dy-1) << 9; |
bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]); |
jbig2_image_set_pixel(image, x, y, bit); |
} |
} |
#ifdef JBIG2_DEBUG_DUMP |
{ |
static count = 0; |
char name[32]; |
snprintf(name, 32, "refin-%d.pbm", count); |
jbig2_image_write_pbm_file(ref, name); |
snprintf(name, 32, "refout-%d.pbm", count); |
jbig2_image_write_pbm_file(image, name); |
count++; |
} |
#endif |
return 0; |
} |
static int |
jbig2_decode_refinement_template1(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2RefinementRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GR_stats) |
{ |
const int GRW = image->width; |
const int GRH = image->height; |
const int stride = image->stride; |
const int refstride = params->reference->stride; |
const int dy = params->DY; |
byte *grreg_line = (byte *)image->data; |
byte *grref_line = (byte *)params->reference->data; |
int x,y; |
for (y = 0; y < GRH; y++) { |
const int padded_width = (GRW + 7) & -8; |
uint32_t CONTEXT; |
uint32_t refline_m1; /* previous line of the reference bitmap */ |
uint32_t refline_0; /* current line of the reference bitmap */ |
uint32_t refline_1; /* next line of the reference bitmap */ |
uint32_t line_m1; /* previous line of the decoded bitmap */ |
line_m1 = (y >= 1) ? grreg_line[-stride] : 0; |
refline_m1 = ((y-dy) >= 1) ? grref_line[(-1-dy)*stride] << 2: 0; |
refline_0 = (((y-dy) > 0) && ((y-dy) < GRH)) ? grref_line[(0-dy)*stride] << 4 : 0; |
refline_1 = (y < GRH - 1) ? grref_line[(+1-dy)*stride] << 7 : 0; |
CONTEXT = ((line_m1 >> 5) & 0x00e) | |
((refline_1 >> 5) & 0x030) | |
((refline_0 >> 5) & 0x1c0) | |
((refline_m1 >> 5) & 0x200); |
for (x = 0; x < padded_width; x += 8) { |
byte result = 0; |
int x_minor; |
const int minor_width = GRW - x > 8 ? 8 : GRW - x; |
if (y >= 1) { |
line_m1 = (line_m1 << 8) | |
(x + 8 < GRW ? grreg_line[-stride + (x >> 3) + 1] : 0); |
refline_m1 = (refline_m1 << 8) | |
(x + 8 < GRW ? grref_line[-refstride + (x >> 3) + 1] << 2 : 0); |
} |
refline_0 = (refline_0 << 8) | |
(x + 8 < GRW ? grref_line[(x >> 3) + 1] << 4 : 0); |
if (y < GRH - 1) |
refline_1 = (refline_1 << 8) | |
(x + 8 < GRW ? grref_line[+refstride + (x >> 3) + 1] << 7 : 0); |
else |
refline_1 = 0; |
/* this is the speed critical inner-loop */ |
for (x_minor = 0; x_minor < minor_width; x_minor++) { |
bool bit; |
bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]); |
result |= bit << (7 - x_minor); |
CONTEXT = ((CONTEXT & 0x0d6) << 1) | bit | |
((line_m1 >> (9 - x_minor)) & 0x002) | |
((refline_1 >> (9 - x_minor)) & 0x010) | |
((refline_0 >> (9 - x_minor)) & 0x040) | |
((refline_m1 >> (9 - x_minor)) & 0x200); |
} |
grreg_line[x>>3] = result; |
} |
grreg_line += stride; |
grref_line += refstride; |
} |
return 0; |
} |
/** |
* jbig2_decode_refinement_region: Decode a generic refinement region. |
* @ctx: The context for allocation and error reporting. |
* @segment: A segment reference for error reporting. |
* @params: Decoding parameter set. |
* @as: Arithmetic decoder state. |
* @image: Where to store the decoded image. |
* @GR_stats: Arithmetic stats. |
* |
* Decodes a generic refinement region, according to section 6.3. |
* an already allocated Jbig2Image object in @image for the result. |
* |
* Because this API is based on an arithmetic decoding state, it is |
* not suitable for MMR decoding. |
* |
* Return code: 0 on success. |
**/ |
int |
jbig2_decode_refinement_region(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2RefinementRegionParams *params, |
Jbig2ArithState *as, |
Jbig2Image *image, |
Jbig2ArithCx *GR_stats) |
{ |
{ |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"decoding generic refinement region with offset %d,%x,\n" |
" GRTEMPLATE=%d, TPGRON=%d, RA1=(%d,%d) RA2=(%d,%d)\n", |
params->DX, params->DY, params->GRTEMPLATE, params->TPGRON, |
params->grat[0], params->grat[1], params->grat[2], params->grat[3]); |
} |
if (params->TPGRON) |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"decode_refinement_region: typical prediction coding NYI"); |
if (params->GRTEMPLATE) |
return jbig2_decode_refinement_template1_unopt(ctx, segment, params, |
as, image, GR_stats); |
else |
return jbig2_decode_refinement_template0_unopt(ctx, segment, params, |
as, image, GR_stats); |
} |
/** |
* Find the first referred-to intermediate region segment |
* with a non-NULL result for use as a reference image |
*/ |
Jbig2Segment * |
jbig2_region_find_referred(Jbig2Ctx *ctx,Jbig2Segment *segment) |
{ |
const int nsegments = segment->referred_to_segment_count; |
Jbig2Segment *rsegment; |
int index; |
for (index = 0; index < nsegments; index++) { |
rsegment = jbig2_find_segment(ctx, |
segment->referred_to_segments[index]); |
if (rsegment == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"could not find referred to segment %d", |
segment->referred_to_segments[index]); |
continue; |
} |
switch (rsegment->flags & 63) { |
case 4: /* intermediate text region */ |
case 20: /* intermediate halftone region */ |
case 36: /* intermediate generic region */ |
case 40: /* intermediate generic refinement region */ |
if (rsegment->result) return rsegment; |
break; |
default: /* keep looking */ |
break; |
} |
} |
/* no appropriate reference was found. */ |
return NULL; |
} |
/** |
* Handler for generic refinement region segments |
*/ |
int |
jbig2_refinement_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data) |
{ |
Jbig2RefinementRegionParams params; |
Jbig2RegionSegmentInfo rsi; |
int offset = 0; |
byte seg_flags; |
/* 7.4.7 */ |
if (segment->data_length < 18) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
jbig2_get_region_segment_info(&rsi, segment_data); |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"generic region: %d x %d @ (%d, %d), flags = %02x", |
rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags); |
/* 7.4.7.2 */ |
seg_flags = segment_data[17]; |
params.GRTEMPLATE = seg_flags & 0x01; |
params.TPGRON = seg_flags & 0x02 ? 1 : 0; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"segment flags = %02x %s%s", seg_flags, |
params.GRTEMPLATE ? " GRTEMPLATE" :"", |
params.TPGRON ? " TPGRON" : "" ); |
if (seg_flags & 0xFC) |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"reserved segment flag bits are non-zero"); |
offset += 18; |
/* 7.4.7.3 */ |
if (!params.GRTEMPLATE) { |
if (segment->data_length < 22) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
params.grat[0] = segment_data[offset + 0]; |
params.grat[1] = segment_data[offset + 1]; |
params.grat[2] = segment_data[offset + 2]; |
params.grat[3] = segment_data[offset + 3]; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"grat1: (%d, %d) grat2: (%d, %d)", |
params.grat[0], params.grat[1], |
params.grat[2], params.grat[3]); |
offset += 4; |
} |
/* 7.4.7.4 - set up the reference image */ |
if (segment->referred_to_segment_count) { |
Jbig2Segment *ref; |
ref = jbig2_region_find_referred(ctx, segment); |
if (ref == NULL) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"could not find reference bitmap!"); |
/* the reference bitmap is the result of a previous |
intermediate region segment; the reference selection |
rules say to use the first one available, and not to |
reuse any intermediate result, so we simply clone it |
and free the original to keep track of this. */ |
params.reference = jbig2_image_clone(ctx, ref->result); |
jbig2_image_release(ctx, ref->result); |
ref->result = NULL; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"found reference bitmap in segment %d", ref->number); |
} else { |
/* the reference is just (a subset of) the page buffer */ |
params.reference = jbig2_image_clone(ctx, |
ctx->pages[ctx->current_page].image); |
/* TODO: subset the image if appropriate */ |
} |
/* 7.4.7.5 */ |
params.DX = 0; |
params.DY = 0; |
{ |
Jbig2WordStream *ws; |
Jbig2ArithState *as; |
Jbig2ArithCx *GR_stats = NULL; |
int stats_size; |
Jbig2Image *image; |
int code; |
image = jbig2_image_new(ctx, rsi.width, rsi.height); |
if (image == NULL) |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"unable to allocate refinement image"); |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"allocated %d x %d image buffer for region decode results", |
rsi.width, rsi.height); |
stats_size = params.GRTEMPLATE ? 1 << 10 : 1 << 13; |
GR_stats = jbig2_alloc(ctx->allocator, stats_size); |
memset(GR_stats, 0, stats_size); |
ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, |
segment->data_length - offset); |
as = jbig2_arith_new(ctx, ws); |
code = jbig2_decode_refinement_region(ctx, segment, ¶ms, |
as, image, GR_stats); |
jbig2_free(ctx->allocator, as); |
jbig2_word_stream_buf_free(ctx, ws); |
jbig2_free(ctx->allocator, GR_stats); |
if ((segment->flags & 63) == 40) { |
/* intermediate region. save the result for later */ |
segment->result = image; |
} else { |
/* immediate region. composite onto the page */ |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"composing %dx%d decoded refinement region onto page at (%d, %d)", |
rsi.width, rsi.height, rsi.x, rsi.y); |
jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], |
image, rsi.x, rsi.y, rsi.op); |
jbig2_image_release(ctx, image); |
} |
} |
return 0; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_segment.c |
---|
0,0 → 1,295 |
/* |
jbig2dec |
Copyright (C) 2002-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> /* size_t */ |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_symbol_dict.h" |
#include "jbig2_metadata.h" |
Jbig2Segment * |
jbig2_parse_segment_header (Jbig2Ctx *ctx, uint8_t *buf, size_t buf_size, |
size_t *p_header_size) |
{ |
Jbig2Segment *result; |
uint8_t rtscarf; |
uint32_t rtscarf_long; |
uint32_t *referred_to_segments; |
int referred_to_segment_count; |
int referred_to_segment_size; |
int pa_size; |
int offset; |
/* minimum possible size of a jbig2 segment header */ |
if (buf_size < 11) |
return NULL; |
result = (Jbig2Segment *)jbig2_alloc(ctx->allocator, |
sizeof(Jbig2Segment)); |
/* 7.2.2 */ |
result->number = jbig2_get_int32(buf); |
/* 7.2.3 */ |
result->flags = buf[4]; |
/* 7.2.4 referred-to segments */ |
rtscarf = buf[5]; |
if ((rtscarf & 0xe0) == 0xe0) |
{ |
rtscarf_long = jbig2_get_int32(buf + 5); |
referred_to_segment_count = rtscarf_long & 0x1fffffff; |
offset = 5 + 4 + (referred_to_segment_count + 1) / 8; |
} |
else |
{ |
referred_to_segment_count = (rtscarf >> 5); |
offset = 5 + 1; |
} |
result->referred_to_segment_count = referred_to_segment_count; |
/* we now have enough information to compute the full header length */ |
referred_to_segment_size = result->number <= 256 ? 1: |
result->number <= 65536 ? 2 : 4; /* 7.2.5 */ |
pa_size = result->flags & 0x40 ? 4 : 1; /* 7.2.6 */ |
if (offset + referred_to_segment_count*referred_to_segment_size + pa_size + 4 > buf_size) |
{ |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, |
"jbig2_parse_segment_header() called with insufficient data", -1); |
jbig2_free (ctx->allocator, result); |
return NULL; |
} |
/* 7.2.5 */ |
if (referred_to_segment_count) |
{ |
int i; |
referred_to_segments = jbig2_alloc(ctx->allocator, referred_to_segment_count * referred_to_segment_size * sizeof(uint32_t)); |
for (i = 0; i < referred_to_segment_count; i++) { |
referred_to_segments[i] = |
(referred_to_segment_size == 1) ? buf[offset] : |
(referred_to_segment_size == 2) ? jbig2_get_int16(buf+offset) : |
jbig2_get_int32(buf + offset); |
offset += referred_to_segment_size; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, |
"segment %d refers to segment %d", |
result->number, referred_to_segments[i]); |
} |
result->referred_to_segments = referred_to_segments; |
} |
else /* no referred-to segments */ |
{ |
result->referred_to_segments = NULL; |
} |
/* 7.2.6 */ |
if (result->flags & 0x40) { |
result->page_association = jbig2_get_int32(buf + offset); |
offset += 4; |
} else { |
result->page_association = buf[offset++]; |
} |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, |
"segment %d is associated with page %d", |
result->number, result->page_association); |
/* 7.2.7 */ |
result->data_length = jbig2_get_int32(buf + offset); |
*p_header_size = offset + 4; |
/* no body parsing results yet */ |
result->result = NULL; |
return result; |
} |
void |
jbig2_free_segment (Jbig2Ctx *ctx, Jbig2Segment *segment) |
{ |
if (segment->referred_to_segments != NULL) { |
jbig2_free(ctx->allocator, segment->referred_to_segments); |
} |
/* todo: we need either some separate fields or |
a more complex result object rather than this |
brittle special casing */ |
switch (segment->flags & 63) { |
case 0: /* symbol dictionary */ |
if (segment->result != NULL) |
jbig2_sd_release(ctx, segment->result); |
break; |
case 4: /* intermediate text region */ |
case 40: /* intermediate refinement region */ |
if (segment->result != NULL) |
jbig2_image_release(ctx, segment->result); |
break; |
case 62: |
if (segment->result != NULL) |
jbig2_metadata_free(ctx, segment->result); |
break; |
default: |
/* anything else is probably an undefined pointer */ |
break; |
} |
jbig2_free (ctx->allocator, segment); |
} |
/* find a segment by number */ |
Jbig2Segment * |
jbig2_find_segment(Jbig2Ctx *ctx, uint32_t number) |
{ |
int index, index_max = ctx->segment_index - 1; |
const Jbig2Ctx *global_ctx = ctx->global_ctx; |
/* FIXME: binary search would be better */ |
for (index = index_max; index >= 0; index--) |
if (ctx->segments[index]->number == number) |
return (ctx->segments[index]); |
if (global_ctx) |
for (index = global_ctx->segment_index - 1; index >= 0; index--) |
if (global_ctx->segments[index]->number == number) |
return (global_ctx->segments[index]); |
/* didn't find a match */ |
return NULL; |
} |
/* parse the generic portion of a region segment data header */ |
void |
jbig2_get_region_segment_info(Jbig2RegionSegmentInfo *info, |
const uint8_t *segment_data) |
{ |
/* 7.4.1 */ |
info->width = jbig2_get_int32(segment_data); |
info->height = jbig2_get_int32(segment_data + 4); |
info->x = jbig2_get_int32(segment_data + 8); |
info->y = jbig2_get_int32(segment_data + 12); |
info->flags = segment_data[16]; |
info->op = info->flags & 0x7; |
} |
/* dispatch code for extension segment parsing */ |
int jbig2_parse_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data) |
{ |
uint32_t type; |
bool reserved, dependent, necessary; |
type = jbig2_get_int32(segment_data); |
reserved = type & 0x20000000; |
dependent = type & 0x40000000; |
necessary = type & 0x80000000; |
if (necessary && !reserved) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"extension segment is marked 'necessary' but not 'reservered' contrary to spec"); |
} |
switch (type) { |
case 0x20000000: return jbig2_comment_ascii(ctx, segment, segment_data); |
case 0x20000002: return jbig2_comment_unicode(ctx, segment, segment_data); |
default: |
if (necessary) { |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"unhandled necessary extension segment type 0x%08x", type); |
} else { |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled extension segment"); |
} |
} |
return 0; |
} |
/* general segment parsing dispatch */ |
int jbig2_parse_segment (Jbig2Ctx *ctx, Jbig2Segment *segment, |
const uint8_t *segment_data) |
{ |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"Segment %d, flags=%x, type=%d, data_length=%d", |
segment->number, segment->flags, segment->flags & 63, |
segment->data_length); |
switch (segment->flags & 63) |
{ |
case 0: |
return jbig2_symbol_dictionary(ctx, segment, segment_data); |
case 4: /* intermediate text region */ |
case 6: /* immediate text region */ |
case 7: /* immediate lossless text region */ |
return jbig2_text_region(ctx, segment, segment_data); |
#ifdef JBIG2_HALFTONE |
case 16: |
return jbig2_pattern_dictionary(ctx, segment, segment_data); |
case 20: /* intermediate halftone region */ |
case 22: /* immediate halftone region */ |
case 23: /* immediate lossless halftone region */ |
return jbig2_halftone_region(ctx, segment, segment_data); |
#else |
case 16: |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled segment type 'pattern dictionary'"); |
case 20: |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled segment type 'intermediate halftone region'"); |
case 22: |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled segment type 'immediate halftone region'"); |
case 23: |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled segment type 'immediate lossless halftone region'"); |
#endif |
case 36: |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled segment type 'intermediate generic region'"); |
case 38: /* immediate generic region */ |
case 39: /* immediate lossless generic region */ |
return jbig2_immediate_generic_region(ctx, segment, segment_data); |
case 40: /* intermediate generic refinement region */ |
case 42: /* immediate generic refinement region */ |
case 43: /* immediate lossless generic refinement region */ |
return jbig2_refinement_region(ctx, segment, segment_data); |
case 48: |
return jbig2_page_info(ctx, segment, segment_data); |
case 49: |
return jbig2_end_of_page(ctx, segment, segment_data); |
case 50: |
return jbig2_end_of_stripe(ctx, segment, segment_data); |
case 51: |
ctx->state = JBIG2_FILE_EOF; |
return jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"end of file"); |
case 52: |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled segment type 'profile'"); |
case 53: |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unhandled table segment"); |
case 62: |
return jbig2_parse_extension_segment(ctx, segment, segment_data); |
default: |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unknown segment type %d", segment->flags & 63); |
} |
return 0; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_symbol_dict.c |
---|
0,0 → 1,937 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* symbol dictionary segment decode and support */ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> |
#include <string.h> /* memset() */ |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#include "jbig2_arith_int.h" |
#include "jbig2_arith_iaid.h" |
#include "jbig2_huffman.h" |
#include "jbig2_generic.h" |
#include "jbig2_mmr.h" |
#include "jbig2_symbol_dict.h" |
#include "jbig2_text.h" |
#if defined(OUTPUT_PBM) || defined(DUMP_SYMDICT) |
#include <stdio.h> |
#include "jbig2_image.h" |
#endif |
/* Table 13 */ |
typedef struct { |
bool SDHUFF; |
bool SDREFAGG; |
int32_t SDNUMINSYMS; |
Jbig2SymbolDict *SDINSYMS; |
uint32_t SDNUMNEWSYMS; |
uint32_t SDNUMEXSYMS; |
Jbig2HuffmanTable *SDHUFFDH; |
Jbig2HuffmanTable *SDHUFFDW; |
Jbig2HuffmanTable *SDHUFFBMSIZE; |
Jbig2HuffmanTable *SDHUFFAGGINST; |
int SDTEMPLATE; |
int8_t sdat[8]; |
bool SDRTEMPLATE; |
int8_t sdrat[4]; |
} Jbig2SymbolDictParams; |
/* Utility routines */ |
#ifdef DUMP_SYMDICT |
void |
jbig2_dump_symbol_dict(Jbig2Ctx *ctx, Jbig2Segment *segment) |
{ |
Jbig2SymbolDict *dict = (Jbig2SymbolDict *)segment->result; |
int index; |
char filename[24]; |
if (dict == NULL) return; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"dumping symbol dict as %d individual png files\n", dict->n_symbols); |
for (index = 0; index < dict->n_symbols; index++) { |
snprintf(filename, sizeof(filename), "symbol_%02d-%04d.png", |
segment->number, index); |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"dumping symbol %d/%d as '%s'", index, dict->n_symbols, filename); |
#ifdef HAVE_LIBPNG |
jbig2_image_write_png_file(dict->glyphs[index], filename); |
#else |
jbig2_image_write_pbm_file(dict->glyphs[index], filename); |
#endif |
} |
} |
#endif /* DUMP_SYMDICT */ |
/* return a new empty symbol dict */ |
Jbig2SymbolDict * |
jbig2_sd_new(Jbig2Ctx *ctx, int n_symbols) |
{ |
Jbig2SymbolDict *new = NULL; |
new = (Jbig2SymbolDict *)jbig2_alloc(ctx->allocator, |
sizeof(Jbig2SymbolDict)); |
if (new != NULL) { |
new->glyphs = (Jbig2Image **)jbig2_alloc(ctx->allocator, |
n_symbols*sizeof(Jbig2Image*)); |
new->n_symbols = n_symbols; |
} else { |
return NULL; |
} |
if (new->glyphs != NULL) { |
memset(new->glyphs, 0, n_symbols*sizeof(Jbig2Image*)); |
} else { |
jbig2_free(ctx->allocator, new); |
return NULL; |
} |
return new; |
} |
/* release the memory associated with a symbol dict */ |
void |
jbig2_sd_release(Jbig2Ctx *ctx, Jbig2SymbolDict *dict) |
{ |
int i; |
if (dict == NULL) return; |
for (i = 0; i < dict->n_symbols; i++) |
if (dict->glyphs[i]) jbig2_image_release(ctx, dict->glyphs[i]); |
jbig2_free(ctx->allocator, dict->glyphs); |
jbig2_free(ctx->allocator, dict); |
} |
/* get a particular glyph by index */ |
Jbig2Image * |
jbig2_sd_glyph(Jbig2SymbolDict *dict, unsigned int id) |
{ |
if (dict == NULL) return NULL; |
return dict->glyphs[id]; |
} |
/* count the number of dictionary segments referred to by the given segment */ |
int |
jbig2_sd_count_referred(Jbig2Ctx *ctx, Jbig2Segment *segment) |
{ |
int index; |
Jbig2Segment *rsegment; |
int n_dicts = 0; |
for (index = 0; index < segment->referred_to_segment_count; index++) { |
rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]); |
if (rsegment && ((rsegment->flags & 63) == 0)) n_dicts++; |
} |
return (n_dicts); |
} |
/* return an array of pointers to symbol dictionaries referred to by the given segment */ |
Jbig2SymbolDict ** |
jbig2_sd_list_referred(Jbig2Ctx *ctx, Jbig2Segment *segment) |
{ |
int index; |
Jbig2Segment *rsegment; |
Jbig2SymbolDict **dicts; |
int n_dicts = jbig2_sd_count_referred(ctx, segment); |
int dindex = 0; |
dicts = jbig2_alloc(ctx->allocator, sizeof(Jbig2SymbolDict *) * n_dicts); |
for (index = 0; index < segment->referred_to_segment_count; index++) { |
rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]); |
if (rsegment && ((rsegment->flags & 63) == 0)) { |
/* add this referred to symbol dictionary */ |
dicts[dindex++] = (Jbig2SymbolDict *)rsegment->result; |
} |
} |
if (dindex != n_dicts) { |
/* should never happen */ |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"counted %d symbol dictionaries but build a list with %d.\n", |
n_dicts, dindex); |
} |
return (dicts); |
} |
/* generate a new symbol dictionary by concatenating a list of |
existing dictionaries */ |
Jbig2SymbolDict * |
jbig2_sd_cat(Jbig2Ctx *ctx, int n_dicts, Jbig2SymbolDict **dicts) |
{ |
int i,j,k, symbols; |
Jbig2SymbolDict *new = NULL; |
/* count the imported symbols and allocate a new array */ |
symbols = 0; |
for(i = 0; i < n_dicts; i++) |
symbols += dicts[i]->n_symbols; |
/* fill a new array with cloned glyph pointers */ |
new = jbig2_sd_new(ctx, symbols); |
if (new != NULL) { |
k = 0; |
for (i = 0; i < n_dicts; i++) |
for (j = 0; j < dicts[i]->n_symbols; j++) |
new->glyphs[k++] = jbig2_image_clone(ctx, dicts[i]->glyphs[j]); |
} |
return new; |
} |
/* Decoding routines */ |
/* 6.5 */ |
static Jbig2SymbolDict * |
jbig2_decode_symbol_dict(Jbig2Ctx *ctx, |
Jbig2Segment *segment, |
const Jbig2SymbolDictParams *params, |
const byte *data, size_t size, |
Jbig2ArithCx *GB_stats, |
Jbig2ArithCx *GR_stats) |
{ |
Jbig2SymbolDict *SDNEWSYMS; |
Jbig2SymbolDict *SDEXSYMS; |
int32_t HCHEIGHT; |
uint32_t NSYMSDECODED; |
int32_t SYMWIDTH, TOTWIDTH; |
uint32_t HCFIRSTSYM; |
uint32_t *SDNEWSYMWIDTHS = NULL; |
int SBSYMCODELEN = 0; |
Jbig2WordStream *ws = NULL; |
Jbig2HuffmanState *hs = NULL; |
Jbig2HuffmanTable *SDHUFFRDX = NULL; |
Jbig2ArithState *as = NULL; |
Jbig2ArithIntCtx *IADH = NULL; |
Jbig2ArithIntCtx *IADW = NULL; |
Jbig2ArithIntCtx *IAEX = NULL; |
Jbig2ArithIntCtx *IAAI = NULL; |
Jbig2ArithIaidCtx *IAID = NULL; |
Jbig2ArithIntCtx *IARDX = NULL; |
Jbig2ArithIntCtx *IARDY = NULL; |
int code = 0; |
Jbig2SymbolDict **refagg_dicts; |
int n_refagg_dicts = 1; |
Jbig2TextRegionParams *tparams = NULL; |
/* 6.5.5 (3) */ |
HCHEIGHT = 0; |
NSYMSDECODED = 0; |
ws = jbig2_word_stream_buf_new(ctx, data, size); |
if (!params->SDHUFF) { |
as = jbig2_arith_new(ctx, ws); |
IADH = jbig2_arith_int_ctx_new(ctx); |
IADW = jbig2_arith_int_ctx_new(ctx); |
IAEX = jbig2_arith_int_ctx_new(ctx); |
IAAI = jbig2_arith_int_ctx_new(ctx); |
if (params->SDREFAGG) { |
int tmp = params->SDINSYMS->n_symbols + params->SDNUMNEWSYMS; |
for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < tmp; SBSYMCODELEN++); |
IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN); |
IARDX = jbig2_arith_int_ctx_new(ctx); |
IARDY = jbig2_arith_int_ctx_new(ctx); |
} |
} else { |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"huffman coded symbol dictionary"); |
hs = jbig2_huffman_new(ctx, ws); |
SDHUFFRDX = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); |
if (!params->SDREFAGG) { |
SDNEWSYMWIDTHS = jbig2_alloc(ctx->allocator, |
sizeof(*SDNEWSYMWIDTHS)*params->SDNUMNEWSYMS); |
if (SDNEWSYMWIDTHS == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"could not allocate storage for symbol widths"); |
return NULL; |
} |
} |
} |
SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS); |
/* 6.5.5 (4a) */ |
while (NSYMSDECODED < params->SDNUMNEWSYMS) { |
int32_t HCDH, DW; |
/* 6.5.6 */ |
if (params->SDHUFF) { |
HCDH = jbig2_huffman_get(hs, params->SDHUFFDH, &code); |
} else { |
code = jbig2_arith_int_decode(IADH, as, &HCDH); |
} |
if (code != 0) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"error or OOB decoding height class delta (%d)\n", code); |
} |
/* 6.5.5 (4b) */ |
HCHEIGHT = HCHEIGHT + HCDH; |
SYMWIDTH = 0; |
TOTWIDTH = 0; |
HCFIRSTSYM = NSYMSDECODED; |
if (HCHEIGHT < 0) { |
/* todo: mem cleanup */ |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Invalid HCHEIGHT value"); |
return NULL; |
} |
#ifdef JBIG2_DEBUG |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"HCHEIGHT = %d", HCHEIGHT); |
#endif |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"decoding height class %d with %d syms decoded", HCHEIGHT, NSYMSDECODED); |
for (;;) { |
/* check for broken symbol table */ |
if (NSYMSDECODED > params->SDNUMNEWSYMS) |
{ |
/* todo: mem cleanup? */ |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"No OOB signalling end of height class %d", HCHEIGHT); |
break; |
} |
/* 6.5.7 */ |
if (params->SDHUFF) { |
DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code); |
} else { |
code = jbig2_arith_int_decode(IADW, as, &DW); |
} |
/* 6.5.5 (4c.i) */ |
if (code == 1) { |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
" OOB signals end of height class %d", HCHEIGHT); |
break; |
} |
SYMWIDTH = SYMWIDTH + DW; |
TOTWIDTH = TOTWIDTH + SYMWIDTH; |
if (SYMWIDTH < 0) { |
/* todo: mem cleanup */ |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Invalid SYMWIDTH value (%d) at symbol %d", SYMWIDTH, NSYMSDECODED+1); |
return NULL; |
} |
#ifdef JBIG2_DEBUG |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"SYMWIDTH = %d TOTWIDTH = %d", SYMWIDTH, TOTWIDTH); |
#endif |
/* 6.5.5 (4c.ii) */ |
if (!params->SDHUFF || params->SDREFAGG) { |
#ifdef JBIG2_DEBUG |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"SDHUFF = %d; SDREFAGG = %d", params->SDHUFF, params->SDREFAGG); |
#endif |
/* 6.5.8 */ |
if (!params->SDREFAGG) { |
Jbig2GenericRegionParams region_params; |
int sdat_bytes; |
Jbig2Image *image; |
/* Table 16 */ |
region_params.MMR = 0; |
region_params.GBTEMPLATE = params->SDTEMPLATE; |
region_params.TPGDON = 0; |
region_params.USESKIP = 0; |
sdat_bytes = params->SDTEMPLATE == 0 ? 8 : 2; |
memcpy(region_params.gbat, params->sdat, sdat_bytes); |
image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT); |
code = jbig2_decode_generic_region(ctx, segment, ®ion_params, |
as, image, GB_stats); |
/* todo: handle errors */ |
SDNEWSYMS->glyphs[NSYMSDECODED] = image; |
} else { |
/* 6.5.8.2 refinement/aggregate symbol */ |
uint32_t REFAGGNINST; |
if (params->SDHUFF) { |
REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code); |
} else { |
code = jbig2_arith_int_decode(IAAI, as, (int32_t*)&REFAGGNINST); |
} |
if (code || (int32_t)REFAGGNINST <= 0) { |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"invalid number of symbols or OOB in aggregate glyph"); |
return NULL; |
} |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"aggregate symbol coding (%d instances)", REFAGGNINST); |
if (REFAGGNINST > 1) { |
Jbig2Image *image; |
int i; |
if (tparams == NULL) |
{ |
/* First time through, we need to initialise the */ |
/* various tables for Huffman or adaptive encoding */ |
/* as well as the text region parameters structure */ |
refagg_dicts = jbig2_alloc(ctx->allocator, sizeof(Jbig2SymbolDict *) * n_refagg_dicts); |
if (refagg_dicts == NULL) { |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Out of memory allocating dictionary array"); |
return NULL; |
} |
refagg_dicts[0] = jbig2_sd_new(ctx, params->SDNUMINSYMS + params->SDNUMNEWSYMS); |
if (refagg_dicts[0] == NULL) { |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Out of memory allocating symbol dictionary"); |
jbig2_free(ctx->allocator, refagg_dicts); |
return NULL; |
} |
refagg_dicts[0]->n_symbols = params->SDNUMINSYMS + params->SDNUMNEWSYMS; |
for (i=0;i < params->SDNUMINSYMS;i++) |
{ |
refagg_dicts[0]->glyphs[i] = jbig2_image_clone(ctx, params->SDINSYMS->glyphs[i]); |
} |
tparams = jbig2_alloc(ctx->allocator, sizeof(Jbig2TextRegionParams)); |
if (tparams == NULL) { |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Out of memory creating text region params"); |
jbig2_sd_release(ctx, refagg_dicts[0]); |
jbig2_free(ctx->allocator, refagg_dicts); |
return NULL; |
} |
if (!params->SDHUFF) { |
/* Values from Table 17, section 6.5.8.2 (2) */ |
tparams->IADT = jbig2_arith_int_ctx_new(ctx); |
tparams->IAFS = jbig2_arith_int_ctx_new(ctx); |
tparams->IADS = jbig2_arith_int_ctx_new(ctx); |
tparams->IAIT = jbig2_arith_int_ctx_new(ctx); |
/* Table 31 */ |
for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < |
(int)(params->SDNUMINSYMS + params->SDNUMNEWSYMS); SBSYMCODELEN++); |
tparams->IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN); |
tparams->IARI = jbig2_arith_int_ctx_new(ctx); |
tparams->IARDW = jbig2_arith_int_ctx_new(ctx); |
tparams->IARDH = jbig2_arith_int_ctx_new(ctx); |
tparams->IARDX = jbig2_arith_int_ctx_new(ctx); |
tparams->IARDY = jbig2_arith_int_ctx_new(ctx); |
} else { |
tparams->SBHUFFFS = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_F); /* Table B.6 */ |
tparams->SBHUFFDS = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_H); /* Table B.8 */ |
tparams->SBHUFFDT = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_K); /* Table B.11 */ |
tparams->SBHUFFRDW = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); /* Table B.15 */ |
tparams->SBHUFFRDH = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); /* Table B.15 */ |
tparams->SBHUFFRDX = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); /* Table B.15 */ |
tparams->SBHUFFRDY = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); /* Table B.15 */ |
} |
tparams->SBHUFF = params->SDHUFF; |
tparams->SBREFINE = 1; |
tparams->SBSTRIPS = 1; |
tparams->SBDEFPIXEL = 0; |
tparams->SBCOMBOP = JBIG2_COMPOSE_OR; |
tparams->TRANSPOSED = 0; |
tparams->REFCORNER = JBIG2_CORNER_TOPLEFT; |
tparams->SBDSOFFSET = 0; |
tparams->SBRTEMPLATE = params->SDRTEMPLATE; |
} |
tparams->SBNUMINSTANCES = REFAGGNINST; |
image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT); |
if (image == NULL) { |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Out of memory creating symbol image"); |
jbig2_free(ctx->allocator, tparams); |
jbig2_sd_release(ctx, refagg_dicts[0]); |
jbig2_free(ctx->allocator, refagg_dicts); |
return NULL; |
} |
/* multiple symbols are handled as a text region */ |
jbig2_decode_text_region(ctx, segment, tparams, (const Jbig2SymbolDict * const *)refagg_dicts, |
n_refagg_dicts, image, data, size, GR_stats, as, (Jbig2WordStream *)NULL); |
SDNEWSYMS->glyphs[NSYMSDECODED] = image; |
refagg_dicts[0]->glyphs[params->SDNUMINSYMS + NSYMSDECODED] = jbig2_image_clone(ctx, SDNEWSYMS->glyphs[NSYMSDECODED]); |
} else { |
/* 6.5.8.2.2 */ |
/* bool SBHUFF = params->SDHUFF; */ |
Jbig2RefinementRegionParams rparams; |
Jbig2Image *image; |
uint32_t ID; |
int32_t RDX, RDY; |
int ninsyms = params->SDINSYMS->n_symbols; |
if (params->SDHUFF) { |
ID = jbig2_huffman_get_bits(hs, SBSYMCODELEN); |
RDX = jbig2_huffman_get(hs, SDHUFFRDX, &code); |
RDY = jbig2_huffman_get(hs, SDHUFFRDX, &code); |
} else { |
code = jbig2_arith_iaid_decode(IAID, as, (int32_t*)&ID); |
code = jbig2_arith_int_decode(IARDX, as, &RDX); |
code = jbig2_arith_int_decode(IARDY, as, &RDY); |
} |
if (ID >= ninsyms+NSYMSDECODED) { |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"refinement references unknown symbol %d", ID); |
return NULL; |
} |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"symbol is a refinement of id %d with the refinement applied at (%d,%d)", |
ID, RDX, RDY); |
image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT); |
/* Table 18 */ |
rparams.GRTEMPLATE = params->SDRTEMPLATE; |
rparams.reference = (ID < ninsyms) ? |
params->SDINSYMS->glyphs[ID] : |
SDNEWSYMS->glyphs[ID-ninsyms]; |
rparams.DX = RDX; |
rparams.DY = RDY; |
rparams.TPGRON = 0; |
memcpy(rparams.grat, params->sdrat, 4); |
jbig2_decode_refinement_region(ctx, segment, |
&rparams, as, image, GR_stats); |
SDNEWSYMS->glyphs[NSYMSDECODED] = image; |
} |
} |
#ifdef OUTPUT_PBM |
{ |
char name[64]; |
FILE *out; |
snprintf(name, 64, "sd.%04d.%04d.pbm", |
segment->number, NSYMSDECODED); |
out = fopen(name, "wb"); |
jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out); |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"writing out glyph as '%s' ...", name); |
fclose(out); |
} |
#endif |
} |
/* 6.5.5 (4c.iii) */ |
if (params->SDHUFF && !params->SDREFAGG) { |
SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH; |
} |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"decoded symbol %d of %d (%dx%d)", |
NSYMSDECODED, params->SDNUMNEWSYMS, |
SYMWIDTH, HCHEIGHT); |
/* 6.5.5 (4c.iv) */ |
NSYMSDECODED = NSYMSDECODED + 1; |
} /* end height class decode loop */ |
/* 6.5.5 (4d) */ |
if (params->SDHUFF && !params->SDREFAGG) { |
/* 6.5.9 */ |
Jbig2Image *image; |
int BMSIZE = jbig2_huffman_get(hs, params->SDHUFFBMSIZE, &code); |
int j, x; |
if (code || (BMSIZE < 0)) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"error decoding size of collective bitmap!"); |
/* todo: memory cleanup */ |
return NULL; |
} |
/* skip any bits before the next byte boundary */ |
jbig2_huffman_skip(hs); |
image = jbig2_image_new(ctx, TOTWIDTH, HCHEIGHT); |
if (image == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"could not allocate collective bitmap image!"); |
/* todo: memory cleanup */ |
return NULL; |
} |
if (BMSIZE == 0) { |
/* if BMSIZE == 0 bitmap is uncompressed */ |
const byte *src = data + jbig2_huffman_offset(hs); |
const int stride = (image->width >> 3) + |
((image->width & 7) ? 1 : 0); |
byte *dst = image->data; |
BMSIZE = image->height * stride; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"reading %dx%d uncompressed bitmap" |
" for %d symbols (%d bytes)", |
image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE); |
for (j = 0; j < image->height; j++) { |
memcpy(dst, src, stride); |
dst += image->stride; |
src += stride; |
} |
} else { |
Jbig2GenericRegionParams rparams; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"reading %dx%d collective bitmap for %d symbols (%d bytes)", |
image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE); |
rparams.MMR = 1; |
code = jbig2_decode_generic_mmr(ctx, segment, &rparams, |
data + jbig2_huffman_offset(hs), BMSIZE, image); |
if (code) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"error decoding MMR bitmap image!"); |
/* todo: memory cleanup */ |
return NULL; |
} |
} |
/* advance past the data we've just read */ |
jbig2_huffman_advance(hs, BMSIZE); |
/* copy the collective bitmap into the symbol dictionary */ |
x = 0; |
for (j = HCFIRSTSYM; j < NSYMSDECODED; j++) { |
Jbig2Image *glyph; |
glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT); |
jbig2_image_compose(ctx, glyph, image, |
-x, 0, JBIG2_COMPOSE_REPLACE); |
x += SDNEWSYMWIDTHS[j]; |
SDNEWSYMS->glyphs[j] = glyph; |
} |
jbig2_image_release(ctx, image); |
} |
} /* end of symbol decode loop */ |
if (tparams != NULL) |
{ |
if (!params->SDHUFF) |
{ |
jbig2_arith_int_ctx_free(ctx, tparams->IADT); |
jbig2_arith_int_ctx_free(ctx, tparams->IAFS); |
jbig2_arith_int_ctx_free(ctx, tparams->IADS); |
jbig2_arith_int_ctx_free(ctx, tparams->IAIT); |
jbig2_arith_iaid_ctx_free(ctx, tparams->IAID); |
jbig2_arith_int_ctx_free(ctx, tparams->IARI); |
jbig2_arith_int_ctx_free(ctx, tparams->IARDW); |
jbig2_arith_int_ctx_free(ctx, tparams->IARDH); |
jbig2_arith_int_ctx_free(ctx, tparams->IARDX); |
jbig2_arith_int_ctx_free(ctx, tparams->IARDY); |
} |
else |
{ |
jbig2_release_huffman_table(ctx, tparams->SBHUFFFS); |
jbig2_release_huffman_table(ctx, tparams->SBHUFFDS); |
jbig2_release_huffman_table(ctx, tparams->SBHUFFDT); |
jbig2_release_huffman_table(ctx, tparams->SBHUFFRDX); |
jbig2_release_huffman_table(ctx, tparams->SBHUFFRDY); |
jbig2_release_huffman_table(ctx, tparams->SBHUFFRDW); |
jbig2_release_huffman_table(ctx, tparams->SBHUFFRDH); |
} |
jbig2_free(ctx->allocator, tparams); |
tparams = NULL; |
jbig2_sd_release(ctx, refagg_dicts[0]); |
jbig2_free(ctx->allocator, refagg_dicts); |
} |
jbig2_free(ctx->allocator, GB_stats); |
/* 6.5.10 */ |
SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS); |
{ |
int i = 0; |
int j = 0; |
int k, m, exflag = 0; |
int32_t exrunlength; |
if (params->SDINSYMS != NULL) |
m = params->SDINSYMS->n_symbols; |
else |
m = 0; |
while (j < params->SDNUMEXSYMS) { |
if (params->SDHUFF) |
/* FIXME: implement reading from huff table B.1 */ |
exrunlength = params->SDNUMEXSYMS; |
else |
code = jbig2_arith_int_decode(IAEX, as, &exrunlength); |
if (exrunlength > params->SDNUMEXSYMS - j) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"runlength too large in export symbol table (%d > %d - %d)\n", |
exrunlength, params->SDNUMEXSYMS, j); |
jbig2_sd_release(ctx, SDEXSYMS); |
/* skip to the cleanup code and return SDEXSYMS = NULL */ |
SDEXSYMS = NULL; |
break; |
} |
for(k = 0; k < exrunlength; k++) |
if (exflag) { |
SDEXSYMS->glyphs[j++] = (i < m) ? |
jbig2_image_clone(ctx, params->SDINSYMS->glyphs[i]) : |
jbig2_image_clone(ctx, SDNEWSYMS->glyphs[i-m]); |
i++; |
} |
exflag = !exflag; |
} |
} |
jbig2_sd_release(ctx, SDNEWSYMS); |
if (!params->SDHUFF) { |
jbig2_arith_int_ctx_free(ctx, IADH); |
jbig2_arith_int_ctx_free(ctx, IADW); |
jbig2_arith_int_ctx_free(ctx, IAEX); |
jbig2_arith_int_ctx_free(ctx, IAAI); |
if (params->SDREFAGG) { |
jbig2_arith_iaid_ctx_free(ctx, IAID); |
jbig2_arith_int_ctx_free(ctx, IARDX); |
jbig2_arith_int_ctx_free(ctx, IARDY); |
} |
jbig2_free(ctx->allocator, as); |
} else { |
if (params->SDREFAGG) { |
jbig2_free(ctx->allocator, SDNEWSYMWIDTHS); |
} |
jbig2_release_huffman_table(ctx, SDHUFFRDX); |
jbig2_free(ctx->allocator, hs); |
} |
jbig2_word_stream_buf_free(ctx, ws); |
return SDEXSYMS; |
} |
/* 7.4.2 */ |
int |
jbig2_symbol_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data) |
{ |
Jbig2SymbolDictParams params; |
uint16_t flags; |
int sdat_bytes; |
int offset; |
Jbig2ArithCx *GB_stats = NULL; |
Jbig2ArithCx *GR_stats = NULL; |
if (segment->data_length < 10) |
goto too_short; |
/* 7.4.2.1.1 */ |
flags = jbig2_get_int16(segment_data); |
params.SDHUFF = flags & 1; |
params.SDREFAGG = (flags >> 1) & 1; |
params.SDTEMPLATE = (flags >> 10) & 3; |
params.SDRTEMPLATE = (flags >> 12) & 1; |
params.SDHUFFDH = NULL; |
params.SDHUFFDW = NULL; |
params.SDHUFFBMSIZE = NULL; |
params.SDHUFFAGGINST = NULL; |
if (params.SDHUFF) { |
switch ((flags & 0x000c) >> 2) { |
case 0: /* Table B.4 */ |
params.SDHUFFDH = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_D); |
break; |
case 1: /* Table B.5 */ |
params.SDHUFFDH = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_E); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"symbol dictionary uses custom DH huffman table (NYI)"); |
case 2: |
default: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"symbol dictionary specified invalid huffman table"); |
break; |
} |
switch ((flags & 0x0030) >> 4) { |
case 0: /* Table B.2 */ |
params.SDHUFFDW = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_B); |
break; |
case 1: /* Table B.3 */ |
params.SDHUFFDW = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_C); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"symbol dictionary uses custom DW huffman table (NYI)"); |
case 2: |
default: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"symbol dictionary specified invalid huffman table"); |
break; |
} |
if (flags & 0x0040) { |
/* Custom table from referred segment */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"symbol dictionary uses custom BMSIZE huffman table (NYI)"); |
} else { |
/* Table B.1 */ |
params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_A); |
} |
if (flags & 0x0080) { |
/* Custom table from referred segment */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"symbol dictionary uses custom REFAGG huffman table (NYI)"); |
} else { |
/* Table B.1 */ |
params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_A); |
} |
} |
/* FIXME: there are quite a few of these conditions to check */ |
/* maybe #ifdef CONFORMANCE and a separate routine */ |
if (!params.SDHUFF) { |
if (flags & 0x000c) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"SDHUFF is zero, but contrary to spec SDHUFFDH is not."); |
} |
if (flags & 0x0030) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"SDHUFF is zero, but contrary to spec SDHUFFDW is not."); |
} |
} |
if (flags & 0x0080) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"bitmap coding context is used (NYI) symbol data likely to be garbage!"); |
} |
/* 7.4.2.1.2 */ |
sdat_bytes = params.SDHUFF ? 0 : params.SDTEMPLATE == 0 ? 8 : 2; |
memcpy(params.sdat, segment_data + 2, sdat_bytes); |
offset = 2 + sdat_bytes; |
/* 7.4.2.1.3 */ |
if (params.SDREFAGG && !params.SDRTEMPLATE) { |
if (offset + 4 > segment->data_length) |
goto too_short; |
memcpy(params.sdrat, segment_data + offset, 4); |
offset += 4; |
} else { |
/* sdrat is meaningless if SDRTEMPLATE is 1, but set a value |
to avoid confusion if anybody looks */ |
memset(params.sdrat, 0, 4); |
} |
if (offset + 8 > segment->data_length) |
goto too_short; |
/* 7.4.2.1.4 */ |
params.SDNUMEXSYMS = jbig2_get_int32(segment_data + offset); |
/* 7.4.2.1.5 */ |
params.SDNUMNEWSYMS = jbig2_get_int32(segment_data + offset + 4); |
offset += 8; |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"symbol dictionary, flags=%04x, %d exported syms, %d new syms", |
flags, params.SDNUMEXSYMS, params.SDNUMNEWSYMS); |
/* 7.4.2.2 (2) */ |
{ |
int n_dicts = jbig2_sd_count_referred(ctx, segment); |
Jbig2SymbolDict **dicts = NULL; |
params.SDINSYMS = NULL; |
if (n_dicts > 0) { |
dicts = jbig2_sd_list_referred(ctx, segment); |
params.SDINSYMS = jbig2_sd_cat(ctx, n_dicts, dicts); |
} |
if (params.SDINSYMS != NULL) { |
params.SDNUMINSYMS = params.SDINSYMS->n_symbols; |
} else { |
params.SDNUMINSYMS = 0; |
} |
} |
/* 7.4.2.2 (4) */ |
if (!params.SDHUFF) { |
int stats_size = params.SDTEMPLATE == 0 ? 65536 : |
params.SDTEMPLATE == 1 ? 8192 : 1024; |
GB_stats = jbig2_alloc(ctx->allocator, stats_size); |
memset(GB_stats, 0, stats_size); |
if (params.SDREFAGG) { |
stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13; |
GR_stats = jbig2_alloc(ctx->allocator, stats_size); |
memset(GR_stats, 0, stats_size); |
} |
} |
if (flags & 0x0100) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"segment marks bitmap coding context as retained (NYI)"); |
} |
segment->result = (void *)jbig2_decode_symbol_dict(ctx, segment, |
¶ms, |
segment_data + offset, |
segment->data_length - offset, |
GB_stats, GR_stats); |
#ifdef DUMP_SYMDICT |
if (segment->result) jbig2_dump_symbol_dict(ctx, segment); |
#endif |
if (params.SDHUFF) { |
jbig2_release_huffman_table(ctx, params.SDHUFFDH); |
jbig2_release_huffman_table(ctx, params.SDHUFFDW); |
jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE); |
jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST); |
} |
/* todo: retain or free GB_stats, GR_stats */ |
return (segment->result != NULL) ? 0 : -1; |
too_short: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_symbol_dict.h |
---|
0,0 → 1,56 |
/* |
jbig2dec |
Copyright (C) 2001-2002 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* symbol dictionary header */ |
/* the results of decoding a symbol dictionary */ |
typedef struct { |
int n_symbols; |
Jbig2Image **glyphs; |
} Jbig2SymbolDict; |
/* decode a symbol dictionary segment and store the results */ |
int |
jbig2_symbol_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const byte *segment_data); |
/* get a particular glyph by index */ |
Jbig2Image * |
jbig2_sd_glyph(Jbig2SymbolDict *dict, unsigned int id); |
/* return a new empty symbol dict */ |
Jbig2SymbolDict * |
jbig2_sd_new(Jbig2Ctx *ctx, int n_symbols); |
/* release the memory associated with a symbol dict */ |
void |
jbig2_sd_release(Jbig2Ctx *ctx, Jbig2SymbolDict *dict); |
/* generate a new symbol dictionary by concatenating a list of |
existing dictionaries */ |
Jbig2SymbolDict * |
jbig2_sd_cat(Jbig2Ctx *ctx, int n_dicts, |
Jbig2SymbolDict **dicts); |
/* count the number of dictionary segments referred |
to by the given segment */ |
int |
jbig2_sd_count_referred(Jbig2Ctx *ctx, Jbig2Segment *segment); |
/* return an array of pointers to symbol dictionaries referred |
to by a segment */ |
Jbig2SymbolDict ** |
jbig2_sd_list_referred(Jbig2Ctx *ctx, Jbig2Segment *segment); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_text.c |
---|
0,0 → 1,787 |
/* |
jbig2dec |
Copyright (C) 2002-2008 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include "os_types.h" |
#include <stddef.h> |
#include <string.h> /* memset() */ |
#include "jbig2.h" |
#include "jbig2_priv.h" |
#include "jbig2_arith.h" |
#include "jbig2_arith_int.h" |
#include "jbig2_arith_iaid.h" |
#include "jbig2_huffman.h" |
#include "jbig2_generic.h" |
#include "jbig2_symbol_dict.h" |
#include "jbig2_text.h" |
/** |
* jbig2_decode_text_region: decode a text region segment |
* |
* @ctx: jbig2 decoder context |
* @segment: jbig2 segment (header) structure |
* @params: parameters from the text region header |
* @dicts: an array of referenced symbol dictionaries |
* @n_dicts: the number of referenced symbol dictionaries |
* @image: image structure in which to store the decoded region bitmap |
* @data: pointer to text region data to be decoded |
* @size: length of text region data |
* |
* Implements the text region decoding procedure |
* described in section 6.4 of the JBIG2 spec. |
* |
* returns: 0 on success |
**/ |
int |
jbig2_decode_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const Jbig2TextRegionParams *params, |
const Jbig2SymbolDict * const *dicts, const int n_dicts, |
Jbig2Image *image, |
const byte *data, const size_t size, |
Jbig2ArithCx *GR_stats, Jbig2ArithState *as, Jbig2WordStream *ws) |
{ |
/* relevent bits of 6.4.4 */ |
uint32_t NINSTANCES; |
uint32_t ID; |
int32_t STRIPT; |
int32_t FIRSTS; |
int32_t DT; |
int32_t DFS; |
int32_t IDS; |
int32_t CURS; |
int32_t CURT; |
int S,T; |
int x,y; |
bool first_symbol; |
uint32_t index, SBNUMSYMS; |
Jbig2Image *IB; |
Jbig2HuffmanState *hs = NULL; |
Jbig2HuffmanTable *SBSYMCODES = NULL; |
int code = 0; |
int RI; |
SBNUMSYMS = 0; |
for (index = 0; index < n_dicts; index++) { |
SBNUMSYMS += dicts[index]->n_symbols; |
} |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"symbol list contains %d glyphs in %d dictionaries", SBNUMSYMS, n_dicts); |
if (params->SBHUFF) { |
Jbig2HuffmanTable *runcodes; |
Jbig2HuffmanParams runcodeparams; |
Jbig2HuffmanLine runcodelengths[35]; |
Jbig2HuffmanLine *symcodelengths; |
Jbig2HuffmanParams symcodeparams; |
int code, err, len, range, r; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"huffman coded text region"); |
hs = jbig2_huffman_new(ctx, ws); |
/* 7.4.3.1.7 - decode symbol ID Huffman table */ |
/* this is actually part of the segment header, but it is more |
convenient to handle it here */ |
/* parse and build the runlength code huffman table */ |
for (index = 0; index < 35; index++) { |
runcodelengths[index].PREFLEN = jbig2_huffman_get_bits(hs, 4); |
runcodelengths[index].RANGELEN = 0; |
runcodelengths[index].RANGELOW = index; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
" read runcode%d length %d", index, runcodelengths[index].PREFLEN); |
} |
runcodeparams.HTOOB = 0; |
runcodeparams.lines = runcodelengths; |
runcodeparams.n_lines = 35; |
runcodes = jbig2_build_huffman_table(ctx, &runcodeparams); |
if (runcodes == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"error constructing symbol id runcode table!"); |
return -1; |
} |
/* decode the symbol id codelengths using the runlength table */ |
symcodelengths = jbig2_alloc(ctx->allocator, SBNUMSYMS*sizeof(Jbig2HuffmanLine)); |
if (symcodelengths == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"memory allocation failure reading symbol ID huffman table!"); |
return -1; |
} |
index = 0; |
while (index < SBNUMSYMS) { |
code = jbig2_huffman_get(hs, runcodes, &err); |
if (err != 0 || code < 0 || code >= 35) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"error reading symbol ID huffman table!"); |
return err ? err : -1; |
} |
if (code < 32) { |
len = code; |
range = 1; |
} else { |
if (code == 32) { |
len = symcodelengths[index-1].PREFLEN; |
if (index < 1) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"error decoding symbol id table: run length with no antecedent!"); |
/* todo: memory cleanup */ |
return -1; |
} |
} else { |
len = 0; /* code == 33 or 34 */ |
} |
if (code == 32) range = jbig2_huffman_get_bits(hs, 2) + 3; |
else if (code == 33) range = jbig2_huffman_get_bits(hs, 3) + 3; |
else if (code == 34) range = jbig2_huffman_get_bits(hs, 7) + 11; |
} |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
" read runcode%d at index %d (length %d range %d)", code, index, len, range); |
if (index+range > SBNUMSYMS) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"runlength extends %d entries beyond the end of symbol id table!", |
index+range - SBNUMSYMS); |
range = SBNUMSYMS - index; |
} |
for (r = 0; r < range; r++) { |
symcodelengths[index+r].PREFLEN = len; |
symcodelengths[index+r].RANGELEN = 0; |
symcodelengths[index+r].RANGELOW = index + r; |
} |
index += r; |
} |
if (index < SBNUMSYMS) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"runlength codes do not cover the available symbol set"); |
} |
symcodeparams.HTOOB = 0; |
symcodeparams.lines = symcodelengths; |
symcodeparams.n_lines = SBNUMSYMS; |
/* skip to byte boundary */ |
jbig2_huffman_skip(hs); |
/* finally, construct the symbol id huffman table itself */ |
SBSYMCODES = jbig2_build_huffman_table(ctx, &symcodeparams); |
jbig2_free(ctx->allocator, symcodelengths); |
jbig2_release_huffman_table(ctx, runcodes); |
if (SBSYMCODES == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"could not construct Symbol ID huffman table!"); |
return -1; |
} |
} |
/* 6.4.5 (1) */ |
jbig2_image_clear(ctx, image, params->SBDEFPIXEL); |
/* 6.4.6 */ |
if (params->SBHUFF) { |
STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code); |
} else { |
code = jbig2_arith_int_decode(params->IADT, as, &STRIPT); |
} |
/* 6.4.5 (2) */ |
STRIPT *= -(params->SBSTRIPS); |
FIRSTS = 0; |
NINSTANCES = 0; |
/* 6.4.5 (3) */ |
while (NINSTANCES < params->SBNUMINSTANCES) { |
/* (3b) */ |
if (params->SBHUFF) { |
DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code); |
} else { |
code = jbig2_arith_int_decode(params->IADT, as, &DT); |
} |
DT *= params->SBSTRIPS; |
STRIPT += DT; |
first_symbol = TRUE; |
/* 6.4.5 (3c) - decode symbols in strip */ |
for (;;) { |
/* (3c.i) */ |
if (first_symbol) { |
/* 6.4.7 */ |
if (params->SBHUFF) { |
DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code); |
} else { |
code = jbig2_arith_int_decode(params->IAFS, as, &DFS); |
} |
FIRSTS += DFS; |
CURS = FIRSTS; |
first_symbol = FALSE; |
} else { |
/* (3c.ii) / 6.4.8 */ |
if (params->SBHUFF) { |
IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code); |
} else { |
code = jbig2_arith_int_decode(params->IADS, as, &IDS); |
} |
if (code) { |
break; |
} |
CURS += IDS + params->SBDSOFFSET; |
} |
/* (3c.iii) / 6.4.9 */ |
if (params->SBSTRIPS == 1) { |
CURT = 0; |
} else if (params->SBHUFF) { |
CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS); |
} else { |
code = jbig2_arith_int_decode(params->IAIT, as, &CURT); |
} |
T = STRIPT + CURT; |
/* (3b.iv) / 6.4.10 - decode the symbol id */ |
if (params->SBHUFF) { |
ID = jbig2_huffman_get(hs, SBSYMCODES, &code); |
} else { |
code = jbig2_arith_iaid_decode(params->IAID, as, (int *)&ID); |
} |
if (ID >= SBNUMSYMS) { |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"symbol id out of range! (%d/%d)", ID, SBNUMSYMS); |
} |
/* (3c.v) / 6.4.11 - look up the symbol bitmap IB */ |
{ |
uint32_t id = ID; |
index = 0; |
while (id >= dicts[index]->n_symbols) |
id -= dicts[index++]->n_symbols; |
IB = jbig2_image_clone(ctx, dicts[index]->glyphs[id]); |
} |
if (params->SBREFINE) { |
if (params->SBHUFF) { |
RI = jbig2_huffman_get_bits(hs, 1); |
} else { |
code = jbig2_arith_int_decode(params->IARI, as, &RI); |
} |
} else { |
RI = 0; |
} |
if (RI) { |
Jbig2RefinementRegionParams rparams; |
Jbig2Image *IBO; |
int32_t RDW, RDH, RDX, RDY; |
Jbig2Image *refimage; |
int BMSIZE = 0; |
/* 6.4.11 (1, 2, 3, 4) */ |
if (!params->SBHUFF) { |
code = jbig2_arith_int_decode(params->IARDW, as, &RDW); |
code = jbig2_arith_int_decode(params->IARDH, as, &RDH); |
code = jbig2_arith_int_decode(params->IARDX, as, &RDX); |
code = jbig2_arith_int_decode(params->IARDY, as, &RDY); |
} else { |
RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code); |
RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code); |
RDX = jbig2_huffman_get(hs, params->SBHUFFRDX, &code); |
RDY = jbig2_huffman_get(hs, params->SBHUFFRDY, &code); |
BMSIZE = jbig2_huffman_get(hs, params->SBHUFFRSIZE, &code); |
jbig2_huffman_skip(hs); |
} |
/* 6.4.11 (6) */ |
IBO = IB; |
refimage = jbig2_image_new(ctx, IBO->width + RDW, |
IBO->height + RDH); |
if (refimage == NULL) { |
jbig2_image_release(ctx, IBO); |
if (params->SBHUFF) { |
jbig2_release_huffman_table(ctx, SBSYMCODES); |
} |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, |
segment->number, |
"couldn't allocate reference image"); |
} |
/* Table 12 */ |
rparams.GRTEMPLATE = params->SBRTEMPLATE; |
rparams.reference = IBO; |
rparams.DX = (RDW >> 1) + RDX; |
rparams.DY = (RDH >> 1) + RDY; |
rparams.TPGRON = 0; |
memcpy(rparams.grat, params->sbrat, 4); |
jbig2_decode_refinement_region(ctx, segment, |
&rparams, as, refimage, GR_stats); |
IB = refimage; |
jbig2_image_release(ctx, IBO); |
/* 6.4.11 (7) */ |
if (params->SBHUFF) { |
jbig2_huffman_advance(hs, BMSIZE); |
} |
} |
/* (3c.vi) */ |
if ((!params->TRANSPOSED) && (params->REFCORNER > 1)) { |
CURS += IB->width - 1; |
} else if ((params->TRANSPOSED) && !(params->REFCORNER & 1)) { |
CURS += IB->height - 1; |
} |
/* (3c.vii) */ |
S = CURS; |
/* (3c.viii) */ |
if (!params->TRANSPOSED) { |
switch (params->REFCORNER) { |
case JBIG2_CORNER_TOPLEFT: x = S; y = T; break; |
case JBIG2_CORNER_TOPRIGHT: x = S - IB->width + 1; y = T; break; |
case JBIG2_CORNER_BOTTOMLEFT: x = S; y = T - IB->height + 1; break; |
case JBIG2_CORNER_BOTTOMRIGHT: x = S - IB->width + 1; y = T - IB->height + 1; break; |
} |
} else { /* TRANSPOSED */ |
switch (params->REFCORNER) { |
case JBIG2_CORNER_TOPLEFT: x = T; y = S; break; |
case JBIG2_CORNER_TOPRIGHT: x = T - IB->width + 1; y = S; break; |
case JBIG2_CORNER_BOTTOMLEFT: x = T; y = S - IB->height + 1; break; |
case JBIG2_CORNER_BOTTOMRIGHT: x = T - IB->width + 1; y = S - IB->height + 1; break; |
} |
} |
/* (3c.ix) */ |
#ifdef JBIG2_DEBUG |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"composing glyph id %d: %dx%d @ (%d,%d) symbol %d/%d", |
ID, IB->width, IB->height, x, y, NINSTANCES + 1, |
params->SBNUMINSTANCES); |
#endif |
jbig2_image_compose(ctx, image, IB, x, y, params->SBCOMBOP); |
/* (3c.x) */ |
if ((!params->TRANSPOSED) && (params->REFCORNER < 2)) { |
CURS += IB->width -1 ; |
} else if ((params->TRANSPOSED) && (params->REFCORNER & 1)) { |
CURS += IB->height - 1; |
} |
/* (3c.xi) */ |
NINSTANCES++; |
jbig2_image_release(ctx, IB); |
} |
/* end strip */ |
} |
/* 6.4.5 (4) */ |
if (params->SBHUFF) { |
jbig2_release_huffman_table(ctx, SBSYMCODES); |
} |
return 0; |
} |
/** |
* jbig2_text_region: read a text region segment header |
**/ |
int |
jbig2_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data) |
{ |
int offset = 0; |
Jbig2RegionSegmentInfo region_info; |
Jbig2TextRegionParams params; |
Jbig2Image *image; |
Jbig2SymbolDict **dicts; |
int n_dicts; |
uint16_t flags; |
uint16_t huffman_flags = 0; |
Jbig2ArithCx *GR_stats = NULL; |
int code = 0; |
Jbig2WordStream *ws = NULL; |
Jbig2ArithState *as = NULL; |
/* 7.4.1 */ |
if (segment->data_length < 17) |
goto too_short; |
jbig2_get_region_segment_info(®ion_info, segment_data); |
offset += 17; |
/* 7.4.3.1.1 */ |
flags = jbig2_get_int16(segment_data + offset); |
offset += 2; |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"text region header flags 0x%04x", flags); |
params.SBHUFF = flags & 0x0001; |
params.SBREFINE = flags & 0x0002; |
params.LOGSBSTRIPS = (flags & 0x000c) >> 2; |
params.SBSTRIPS = 1 << params.LOGSBSTRIPS; |
params.REFCORNER = (flags & 0x0030) >> 4; |
params.TRANSPOSED = flags & 0x0040; |
params.SBCOMBOP = (flags & 0x0180) >> 7; |
params.SBDEFPIXEL = flags & 0x0200; |
/* SBDSOFFSET is a signed 5 bit integer */ |
params.SBDSOFFSET = (flags & 0x7C00) >> 10; |
if (params.SBDSOFFSET > 0x0f) params.SBDSOFFSET -= 0x20; |
params.SBRTEMPLATE = flags & 0x8000; |
if (params.SBDSOFFSET) { |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"text region has SBDSOFFSET %d", params.SBDSOFFSET); |
} |
if (params.SBHUFF) /* Huffman coding */ |
{ |
/* 7.4.3.1.2 */ |
huffman_flags = jbig2_get_int16(segment_data + offset); |
offset += 2; |
if (huffman_flags & 0x8000) |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"reserved bit 15 of text region huffman flags is not zero"); |
} |
else /* arithmetic coding */ |
{ |
/* 7.4.3.1.3 */ |
if ((params.SBREFINE) && !(params.SBRTEMPLATE)) |
{ |
params.sbrat[0] = segment_data[offset]; |
params.sbrat[1] = segment_data[offset + 1]; |
params.sbrat[2] = segment_data[offset + 2]; |
params.sbrat[3] = segment_data[offset + 3]; |
offset += 4; |
} else { |
/* zero these for the sake of later debug messages */ |
memset(params.sbrat, 0, sizeof(params.sbrat)); |
} |
} |
/* 7.4.3.1.4 */ |
params.SBNUMINSTANCES = jbig2_get_int32(segment_data + offset); |
offset += 4; |
if (params.SBHUFF) { |
/* 7.4.3.1.5 - Symbol ID Huffman table */ |
/* ...this is handled in the segment body decoder */ |
/* 7.4.3.1.6 - Other Huffman table selection */ |
switch (huffman_flags & 0x0003) { |
case 0: /* Table B.6 */ |
params.SBHUFFFS = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_F); |
break; |
case 1: /* Table B.7 */ |
params.SBHUFFFS = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_G); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom FS huffman table (NYI)"); |
break; |
case 2: /* invalid */ |
default: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region specified invalid FS huffman table"); |
break; |
} |
switch ((huffman_flags & 0x000c) >> 2) { |
case 0: /* Table B.8 */ |
params.SBHUFFDS = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_H); |
break; |
case 1: /* Table B.9 */ |
params.SBHUFFDS = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_I); |
break; |
case 2: /* Table B.10 */ |
params.SBHUFFDS = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_J); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom DS huffman table (NYI)"); |
break; |
} |
switch ((huffman_flags & 0x0030) >> 4) { |
case 0: /* Table B.11 */ |
params.SBHUFFDT = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_K); |
break; |
case 1: /* Table B.12 */ |
params.SBHUFFDT = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_L); |
break; |
case 2: /* Table B.13 */ |
params.SBHUFFDT = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_M); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom DT huffman table (NYI)"); |
break; |
} |
switch ((huffman_flags & 0x00c0) >> 6) { |
case 0: /* Table B.14 */ |
params.SBHUFFRDW = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_N); |
break; |
case 1: /* Table B.15 */ |
params.SBHUFFRDW = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom RDW huffman table (NYI)"); |
break; |
case 2: /* invalid */ |
default: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region specified invalid RDW huffman table"); |
break; |
} |
switch ((huffman_flags & 0x0300) >> 8) { |
case 0: /* Table B.14 */ |
params.SBHUFFRDH = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_N); |
break; |
case 1: /* Table B.15 */ |
params.SBHUFFRDH = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom RDH huffman table (NYI)"); |
break; |
case 2: /* invalid */ |
default: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region specified invalid RDH huffman table"); |
break; |
} |
switch ((huffman_flags & 0x0c00) >> 10) { |
case 0: /* Table B.14 */ |
params.SBHUFFRDX = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_N); |
break; |
case 1: /* Table B.15 */ |
params.SBHUFFRDX = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom RDX huffman table (NYI)"); |
break; |
case 2: /* invalid */ |
default: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region specified invalid RDX huffman table"); |
break; |
} |
switch ((huffman_flags & 0x3000) >> 12) { |
case 0: /* Table B.14 */ |
params.SBHUFFRDY = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_N); |
break; |
case 1: /* Table B.15 */ |
params.SBHUFFRDY = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_O); |
break; |
case 3: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom RDY huffman table (NYI)"); |
break; |
case 2: /* invalid */ |
default: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region specified invalid RDY huffman table"); |
break; |
} |
switch ((huffman_flags & 0x4000) >> 14) { |
case 0: /* Table B.1 */ |
params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, |
&jbig2_huffman_params_A); |
break; |
case 1: /* Custom table from referred segment */ |
/* We handle this case later by leaving the table as NULL */ |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region uses custom RSIZE huffman table (NYI)"); |
break; |
} |
if (huffman_flags & 0x8000) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"text region huffman flags bit 15 is set, contrary to spec"); |
} |
/* 7.4.3.1.7 */ |
/* For convenience this is done in the body decoder routine */ |
} |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
"text region: %d x %d @ (%d,%d) %d symbols", |
region_info.width, region_info.height, |
region_info.x, region_info.y, params.SBNUMINSTANCES); |
/* 7.4.3.2 (2) - compose the list of symbol dictionaries */ |
n_dicts = jbig2_sd_count_referred(ctx, segment); |
if (n_dicts != 0) { |
dicts = jbig2_sd_list_referred(ctx, segment); |
} else { |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"text region refers to no symbol dictionaries!"); |
} |
if (dicts == NULL) { |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"unable to retrive symbol dictionaries!" |
" previous parsing error?"); |
} else { |
int index; |
if (dicts[0] == NULL) { |
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, |
segment->number, |
"unable to find first referenced symbol dictionary!"); |
} |
for (index = 1; index < n_dicts; index++) |
if (dicts[index] == NULL) { |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
"unable to find all referenced symbol dictionaries!"); |
n_dicts = index; |
} |
} |
/* 7.4.3.2 (3) */ |
if (!params.SBHUFF && params.SBREFINE) { |
int stats_size = params.SBRTEMPLATE ? 1 << 10 : 1 << 13; |
GR_stats = jbig2_alloc(ctx->allocator, stats_size); |
memset(GR_stats, 0, stats_size); |
} |
image = jbig2_image_new(ctx, region_info.width, region_info.height); |
if (image == NULL) { |
if (!params.SBHUFF && params.SBREFINE) { |
jbig2_free(ctx->allocator, GR_stats); |
} else if (params.SBHUFF) { |
jbig2_release_huffman_table(ctx, params.SBHUFFFS); |
jbig2_release_huffman_table(ctx, params.SBHUFFDS); |
jbig2_release_huffman_table(ctx, params.SBHUFFDT); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDX); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDY); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDW); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDH); |
jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE); |
} |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"couldn't allocate text region image"); |
} |
ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset); |
if (!params.SBHUFF) { |
int SBSYMCODELEN, index; |
int SBNUMSYMS = 0; |
for (index = 0; index < n_dicts; index++) { |
SBNUMSYMS += dicts[index]->n_symbols; |
} |
as = jbig2_arith_new(ctx, ws); |
ws = 0; |
params.IADT = jbig2_arith_int_ctx_new(ctx); |
params.IAFS = jbig2_arith_int_ctx_new(ctx); |
params.IADS = jbig2_arith_int_ctx_new(ctx); |
params.IAIT = jbig2_arith_int_ctx_new(ctx); |
/* Table 31 */ |
for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < SBNUMSYMS; SBSYMCODELEN++); |
params.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN); |
params.IARI = jbig2_arith_int_ctx_new(ctx); |
params.IARDW = jbig2_arith_int_ctx_new(ctx); |
params.IARDH = jbig2_arith_int_ctx_new(ctx); |
params.IARDX = jbig2_arith_int_ctx_new(ctx); |
params.IARDY = jbig2_arith_int_ctx_new(ctx); |
} |
code = jbig2_decode_text_region(ctx, segment, ¶ms, |
(const Jbig2SymbolDict * const *)dicts, n_dicts, image, |
segment_data + offset, segment->data_length - offset, |
GR_stats, as, ws); |
if (!params.SBHUFF && params.SBREFINE) { |
jbig2_free(ctx->allocator, GR_stats); |
} |
if (params.SBHUFF) { |
jbig2_release_huffman_table(ctx, params.SBHUFFFS); |
jbig2_release_huffman_table(ctx, params.SBHUFFDS); |
jbig2_release_huffman_table(ctx, params.SBHUFFDT); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDX); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDY); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDW); |
jbig2_release_huffman_table(ctx, params.SBHUFFRDH); |
jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE); |
} |
else { |
jbig2_arith_int_ctx_free(ctx, params.IADT); |
jbig2_arith_int_ctx_free(ctx, params.IAFS); |
jbig2_arith_int_ctx_free(ctx, params.IADS); |
jbig2_arith_int_ctx_free(ctx, params.IAIT); |
jbig2_arith_iaid_ctx_free(ctx, params.IAID); |
jbig2_arith_int_ctx_free(ctx, params.IARI); |
jbig2_arith_int_ctx_free(ctx, params.IARDW); |
jbig2_arith_int_ctx_free(ctx, params.IARDH); |
jbig2_arith_int_ctx_free(ctx, params.IARDX); |
jbig2_arith_int_ctx_free(ctx, params.IARDY); |
jbig2_free(ctx->allocator, as); |
jbig2_word_stream_buf_free(ctx, ws); |
} |
jbig2_free(ctx->allocator, dicts); |
/* todo: check errors */ |
if ((segment->flags & 63) == 4) { |
/* we have an intermediate region here. save it for later */ |
segment->result = image; |
} else { |
/* otherwise composite onto the page */ |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
"composing %dx%d decoded text region onto page at (%d, %d)", |
region_info.width, region_info.height, region_info.x, region_info.y); |
jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, |
region_info.x, region_info.y, region_info.op); |
jbig2_image_release(ctx, image); |
} |
/* success */ |
return 0; |
too_short: |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
"Segment too short"); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2_text.h |
---|
0,0 → 1,73 |
/* |
jbig2dec |
Copyright (C) 2002-2004 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/** |
* Headers for Text region handling |
**/ |
typedef enum { |
JBIG2_CORNER_BOTTOMLEFT = 0, |
JBIG2_CORNER_TOPLEFT = 1, |
JBIG2_CORNER_BOTTOMRIGHT = 2, |
JBIG2_CORNER_TOPRIGHT = 3 |
} Jbig2RefCorner; |
typedef struct { |
bool SBHUFF; |
bool SBREFINE; |
bool SBDEFPIXEL; |
Jbig2ComposeOp SBCOMBOP; |
bool TRANSPOSED; |
Jbig2RefCorner REFCORNER; |
int SBDSOFFSET; |
/* int SBW; */ |
/* int SBH; */ |
uint32_t SBNUMINSTANCES; |
int LOGSBSTRIPS; |
int SBSTRIPS; |
/* int SBNUMSYMS; */ |
/* SBSYMCODES */ |
/* SBSYMCODELEN */ |
/* SBSYMS */ |
Jbig2HuffmanTable *SBHUFFFS; |
Jbig2HuffmanTable *SBHUFFDS; |
Jbig2HuffmanTable *SBHUFFDT; |
Jbig2HuffmanTable *SBHUFFRDW; |
Jbig2HuffmanTable *SBHUFFRDH; |
Jbig2HuffmanTable *SBHUFFRDX; |
Jbig2HuffmanTable *SBHUFFRDY; |
Jbig2HuffmanTable *SBHUFFRSIZE; |
Jbig2ArithIntCtx *IADT; |
Jbig2ArithIntCtx *IAFS; |
Jbig2ArithIntCtx *IADS; |
Jbig2ArithIntCtx *IAIT; |
Jbig2ArithIaidCtx *IAID; |
Jbig2ArithIntCtx *IARI; |
Jbig2ArithIntCtx *IARDW; |
Jbig2ArithIntCtx *IARDH; |
Jbig2ArithIntCtx *IARDX; |
Jbig2ArithIntCtx *IARDY; |
bool SBRTEMPLATE; |
int8_t sbrat[4]; |
} Jbig2TextRegionParams; |
int |
jbig2_decode_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
const Jbig2TextRegionParams *params, |
const Jbig2SymbolDict * const *dicts, const int n_dicts, |
Jbig2Image *image, |
const byte *data, const size_t size, |
Jbig2ArithCx *GR_stats, |
Jbig2ArithState *as, Jbig2WordStream *ws); |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/jbig2dec.c |
---|
0,0 → 1,513 |
/* |
jbig2dec |
Copyright (C) 2001-2009 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#ifndef PACKAGE |
#define PACKAGE "jbig2dec" |
#endif |
#ifndef VERSION |
#define VERSION "unknown-version" |
#endif |
#include <stdio.h> |
#include <stdlib.h> |
#include <stddef.h> |
#include <string.h> |
#ifdef HAVE_GETOPT_H |
# include <getopt.h> |
#else |
# include "getopt.h" |
#endif |
#include "os_types.h" |
#include "sha1.h" |
#include "jbig2.h" |
#include "jbig2_image.h" |
typedef enum { |
usage,dump,render |
} jbig2dec_mode; |
typedef enum { |
jbig2dec_format_jbig2, |
jbig2dec_format_pbm, |
jbig2dec_format_png, |
jbig2dec_format_none |
} jbig2dec_format; |
typedef struct { |
jbig2dec_mode mode; |
int verbose, hash; |
SHA1_CTX *hash_ctx; |
char *output_file; |
jbig2dec_format output_format; |
} jbig2dec_params_t; |
static int print_version(void); |
static int print_usage(void); |
/* page hashing functions */ |
static void |
hash_init(jbig2dec_params_t *params) |
{ |
params->hash_ctx = malloc(sizeof(SHA1_CTX)); |
if (params->hash_ctx == NULL) { |
fprintf(stderr, "unable to allocate hash state\n"); |
params->hash = 0; |
return; |
} else { |
SHA1_Init(params->hash_ctx); |
} |
} |
static void |
hash_image(jbig2dec_params_t *params, Jbig2Image *image) |
{ |
unsigned int N = image->stride * image->height; |
SHA1_Update(params->hash_ctx, image->data, N); |
} |
static void |
hash_print(jbig2dec_params_t *params, FILE *out) |
{ |
unsigned char md[SHA1_DIGEST_SIZE]; |
char digest[2*SHA1_DIGEST_SIZE + 1]; |
int i; |
SHA1_Final(params->hash_ctx, md); |
for (i = 0; i < SHA1_DIGEST_SIZE; i++) { |
snprintf(&(digest[2*i]), 3, "%02x", md[i]); |
} |
fprintf(out, "%s", digest); |
} |
static void |
hash_free(jbig2dec_params_t *params) |
{ |
free(params->hash_ctx); |
params->hash_ctx = NULL; |
} |
static int |
set_output_format(jbig2dec_params_t *params, const char *format) |
{ |
#ifdef HAVE_LIBPNG |
/* this should really by strncasecmp() |
TODO: we need to provide our own for portability */ |
if (!strncmp(format, "png", 3) || !strncmp(format, "PNG", 3)) { |
params->output_format=jbig2dec_format_png; |
return 0; |
} |
#endif |
/* default to pbm */ |
params->output_format=jbig2dec_format_pbm; |
return 0; |
} |
static int |
parse_options(int argc, char *argv[], jbig2dec_params_t *params) |
{ |
static struct option long_options[] = { |
{"version", 0, NULL, 'V'}, |
{"help", 0, NULL, 'h'}, |
{"quiet", 0, NULL, 'q'}, |
{"verbose", 2, NULL, 'v'}, |
{"dump", 0, NULL, 'd'}, |
{"hash", 0, NULL, 'm'}, |
{"output", 1, NULL, 'o'}, |
{"format", 1, NULL, 't'}, |
{NULL, 0, NULL, 0} |
}; |
int option_idx = 1; |
int option; |
while (1) { |
option = getopt_long(argc, argv, |
"Vh?qvdo:t:", long_options, &option_idx); |
if (option == -1) break; |
switch (option) { |
case 0: /* unknown long option */ |
if (!params->verbose) fprintf(stdout, |
"unrecognized option: --%s\n", |
long_options[option_idx].name); |
break; |
case 'q': |
params->verbose = 0; |
break; |
case 'v': |
if (optarg) params->verbose = atoi(optarg); |
else params->verbose = 2; |
break; |
case 'h': |
case '?': |
params->mode = usage; |
break; |
case 'V': |
/* the GNU Coding Standards suggest --version |
should override all other options */ |
print_version(); |
exit(0); |
break; |
case 'd': |
params->mode=dump; |
break; |
case 'm': |
params->hash = 1; |
break; |
case 'o': |
params->output_file = strdup(optarg); |
break; |
case 't': |
set_output_format(params, optarg); |
break; |
default: |
if (!params->verbose) fprintf(stdout, |
"unrecognized option: -%c\n", option); |
break; |
} |
} |
return (optind); |
} |
static int |
print_version (void) |
{ |
fprintf(stdout, "%s %s\n", PACKAGE, VERSION); |
return 0; |
} |
static int |
print_usage (void) |
{ |
fprintf(stderr, |
"Usage: jbig2dec [options] <file.jbig2>\n" |
" or jbig2dec [options] <global_stream> <page_stream>\n" |
"\n" |
" When invoked with a single file, it attempts to parse it as\n" |
" a normal jbig2 file. Invoked with two files, it treats the\n" |
" first as the global segments, and the second as the segment\n" |
" stream for a particular page. This is useful for examining\n" |
" embedded streams.\n" |
"\n" |
" available options:\n" |
" -h --help this usage summary\n" |
" -q --quiet suppress diagnostic output\n" |
" -v --verbose set the verbosity level\n" |
" -d --dump print the structure of the jbig2 file\n" |
" rather than explicitly decoding\n" |
" --version program name and version information\n" |
" --hash print a hash of the decoded document\n" |
" -o <file> send decoded output to <file>\n" |
" Defaults to the the input with a different\n" |
" extension. Pass '-' for stdout.\n" |
" -t <type> force a particular output file format\n" |
#ifdef HAVE_LIBPNG |
" supported options are 'png' and 'pbm'\n" |
#else |
" the only supported option is 'pbm'\n" |
#endif |
"\n" |
); |
return 1; |
} |
static int |
error_callback(void *error_callback_data, const char *buf, Jbig2Severity severity, |
int32_t seg_idx) |
{ |
const jbig2dec_params_t *params = error_callback_data; |
char *type; |
char segment[22]; |
switch (severity) { |
case JBIG2_SEVERITY_DEBUG: |
if (params->verbose < 3) return 0; |
type = "DEBUG"; break;; |
case JBIG2_SEVERITY_INFO: |
if (params->verbose < 2) return 0; |
type = "info"; break;; |
case JBIG2_SEVERITY_WARNING: |
if (params->verbose < 1) return 0; |
type = "WARNING"; break;; |
case JBIG2_SEVERITY_FATAL: type = "FATAL ERROR"; break;; |
default: type = "unknown message"; break;; |
} |
if (seg_idx == -1) segment[0] = '\0'; |
else snprintf(segment, sizeof(segment), "(segment 0x%02x)", seg_idx); |
fprintf(stderr, "jbig2dec %s %s %s\n", type, buf, segment); |
return 0; |
} |
static char * |
make_output_filename(const char *input_filename, const char *extension) |
{ |
char *output_filename; |
const char *c, *e; |
int len; |
if (extension == NULL) { |
fprintf(stderr, "make_output_filename called with no extension!\n"); |
exit (1); |
} |
if (input_filename == NULL) |
c = "out"; |
else { |
/* strip any leading path */ |
c = strrchr(input_filename, '/'); /* *nix */ |
if (c == NULL) |
c = strrchr(input_filename, '\\'); /* win32/dos */ |
if (c != NULL) |
c++; /* skip the path separator */ |
else |
c = input_filename; /* no leading path */ |
} |
/* make sure we haven't just stripped the last character */ |
if (*c == '\0') |
c = "out"; |
/* strip the extension */ |
len = strlen(c); |
e = strrchr(c, '.'); |
if (e != NULL) |
len -= strlen(e); |
/* allocate enough space for the base + ext */ |
output_filename = malloc(len + strlen(extension) + 1); |
if (output_filename == NULL) { |
fprintf(stderr, "couldn't allocate memory for output_filename\n"); |
exit (1); |
} |
strncpy(output_filename, c, len); |
strncpy(output_filename + len, extension, strlen(extension)); |
*(output_filename + len + strlen(extension)) = '\0'; |
/* return the new string */ |
return (output_filename); |
} |
static int |
write_page_image(jbig2dec_params_t *params, Jbig2Image *image) |
{ |
if (!strncmp(params->output_file, "-", 2)) |
{ |
switch (params->output_format) { |
#ifdef HAVE_LIBPNG |
case jbig2dec_format_png: |
jbig2_image_write_png(image, stdout); |
break; |
#endif |
case jbig2dec_format_pbm: |
jbig2_image_write_pbm(image, stdout); |
break; |
default: |
fprintf(stderr, "unsupported output format.\n"); |
return 1; |
} |
} |
else |
{ |
if (params->verbose > 1) |
fprintf(stderr, "saving decoded page as '%s'\n", params->output_file); |
switch (params->output_format) { |
#ifdef HAVE_LIBPNG |
case jbig2dec_format_png: |
jbig2_image_write_png_file(image, params->output_file); |
break; |
#endif |
case jbig2dec_format_pbm: |
jbig2_image_write_pbm_file(image, params->output_file); |
break; |
default: |
fprintf(stderr, "unsupported output format.\n"); |
return 1; |
} |
} |
return 0; |
} |
static int |
write_document_hash(jbig2dec_params_t *params) |
{ |
FILE *out; |
if (!strncmp(params->output_file, "-", 2)) { |
out = stderr; |
} else { |
out = stdout; |
} |
fprintf(out, "Hash of decoded document: "); |
hash_print(params, out); |
fprintf(out, "\n"); |
return 0; |
} |
int |
main (int argc, char **argv) |
{ |
FILE *f = NULL, *f_page = NULL; |
Jbig2Ctx *ctx; |
uint8_t buf[4096]; |
jbig2dec_params_t params; |
int filearg; |
/* set defaults */ |
params.mode = render; |
params.verbose = 1; |
params.hash = 0; |
params.output_file = NULL; |
params.output_format = jbig2dec_format_none; |
filearg = parse_options(argc, argv, ¶ms); |
if (params.hash) hash_init(¶ms); |
switch (params.mode) { |
case usage: |
print_usage(); |
exit (0); |
break; |
case dump: |
fprintf(stderr, "Sorry, segment dump not yet implemented\n"); |
break; |
case render: |
if ((argc - filearg) == 1) |
/* only one argument--open as a jbig2 file */ |
{ |
char *fn = argv[filearg]; |
f = fopen(fn, "rb"); |
if (f == NULL) |
{ |
fprintf(stderr, "error opening %s\n", fn); |
return 1; |
} |
} |
else if ((argc - filearg) == 2) |
/* two arguments open as separate global and page streams */ |
{ |
char *fn = argv[filearg]; |
char *fn_page = argv[filearg+1]; |
f = fopen(fn, "rb"); |
if (f == NULL) |
{ |
fprintf(stderr, "error opening %s\n", fn); |
return 1; |
} |
f_page = fopen(fn_page, "rb"); |
if (f_page == NULL) |
{ |
fprintf(stderr, "error opening %s\n", fn_page); |
return 1; |
} |
} |
else |
/* any other number of arguments */ |
return print_usage(); |
ctx = jbig2_ctx_new(NULL, f_page != NULL ? JBIG2_OPTIONS_EMBEDDED : 0, |
NULL, |
error_callback, ¶ms); |
/* pull the whole file/global stream into memory */ |
for (;;) |
{ |
int n_bytes = fread(buf, 1, sizeof(buf), f); |
if (n_bytes <= 0) |
break; |
if (jbig2_data_in(ctx, buf, n_bytes)) |
break; |
} |
fclose(f); |
/* if there's a local page stream read that in its entirety */ |
if (f_page != NULL) |
{ |
Jbig2GlobalCtx *global_ctx = jbig2_make_global_ctx(ctx); |
ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, global_ctx, |
error_callback, ¶ms); |
for (;;) |
{ |
int n_bytes = fread(buf, 1, sizeof(buf), f_page); |
if (n_bytes <= 0) |
break; |
if (jbig2_data_in(ctx, buf, n_bytes)) |
break; |
} |
fclose(f_page); |
jbig2_global_ctx_free(global_ctx); |
} |
/* retrieve and output the returned pages */ |
{ |
Jbig2Image *image; |
/* work around broken CVision embedded streams */ |
if (f_page != NULL) |
jbig2_complete_page(ctx); |
if (params.output_file == NULL) |
{ |
#ifdef HAVE_LIBPNG |
params.output_file = make_output_filename(argv[filearg], ".png"); |
params.output_format = jbig2dec_format_png; |
#else |
params.output_file = make_output_filename(argv[filearg], ".pbm"); |
params.output_format = jbig2dec_format_pbm; |
#endif |
} else { |
int len = strlen(params.output_file); |
if ((len >= 3) && (params.output_format == jbig2dec_format_none)) |
/* try to set the output type by the given extension */ |
set_output_format(¶ms, params.output_file + len - 3); |
} |
/* retrieve and write out all the completed pages */ |
while ((image = jbig2_page_out(ctx)) != NULL) { |
write_page_image(¶ms, image); |
if (params.hash) hash_image(¶ms, image); |
jbig2_release_page(ctx, image); |
} |
if (params.hash) write_document_hash(¶ms); |
} |
jbig2_ctx_free(ctx); |
} /* end params.mode switch */ |
if (params.output_file) free(params.output_file); |
if (params.hash) hash_free(¶ms); |
/* fin */ |
return 0; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/memcmp.c |
---|
0,0 → 1,49 |
/* |
jbig2dec |
Copyright (C) 2001-2005 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include <stddef.h> |
/* replacement for broken memcmp() */ |
/* |
* compares two byte strings 'a' and 'b', both assumed to be 'len' bytes long |
* returns zero if the two strings are identical, otherwise returns -1 or 1 |
* depending on the relative magnitude of the first differing elements, |
* considered as unsigned chars |
*/ |
int memcmp(const void *b1, const void *b2, size_t len) |
{ |
unsigned char *a, *b; |
size_t i; |
a = (unsigned char *)b1; |
b = (unsigned char *)b2; |
for(i = 0; i < len; i++) { |
if (*a != *b) { |
/* strings differ */ |
return (*a < *b) ? -1 : 1; |
} |
a++; |
b++; |
} |
/* strings match */ |
return 0; |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/os_types.h |
---|
0,0 → 1,51 |
/* |
jbig2dec |
Copyright (C) 2003 Artifex Software, Inc. |
This software is distributed under license and may not |
be copied, modified or distributed except as expressly |
authorized under the terms of the license contained in |
the file LICENSE in this distribution. |
For further licensing information refer to http://artifex.com/ or |
contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
*/ |
/* |
indirection layer for build and platform-specific definitions |
in general, this header should ensure that the stdint types are |
available, and that any optional compile flags are defined if |
the build system doesn't pass them directly. |
*/ |
#ifndef _JBIG2_OS_TYPES_H |
#define _JBIG2_OS_TYPES_H |
#if defined(__CYGWIN__) && !defined(HAVE_STDINT_H) |
# include <sys/types.h> |
# if defined(OLD_CYGWIN_SYS_TYPES) |
/* |
* Old versions of Cygwin have no stdint.h but define "MS types". Some of |
* them conflict with a standard type emulation provided by config_types.h |
* so we do a fixup here. |
*/ |
typedef u_int8_t uint8_t; |
typedef u_int16_t uint16_t; |
typedef u_int32_t uint32_t; |
#endif |
#elif defined(HAVE_CONFIG_H) |
# include "config_types.h" |
#elif defined(_WIN32) || defined(__WIN32__) |
# include "config_win32.h" |
#endif |
#if defined(HAVE_STDINT_H) || defined(__MACOS__) |
# include <stdint.h> |
#elif defined(__VMS) |
# include <inttypes.h> |
#endif |
#endif /* _JBIG2_OS_TYPES_H */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/sha1.c |
---|
0,0 → 1,375 |
/* |
SHA-1 in C |
By Steve Reid <sreid@sea-to-sky.net> |
100% Public Domain |
----------------- |
Modified 7/98 |
By James H. Brown <jbrown@burgoyne.com> |
Still 100% Public Domain |
Corrected a problem which generated improper hash values on 16 bit machines |
Routine SHA1Update changed from |
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int |
len) |
to |
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned |
long len) |
The 'len' parameter was declared an int which works fine on 32 bit machines. |
However, on 16 bit machines an int is too small for the shifts being done |
against |
it. This caused the hash function to generate incorrect values if len was |
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). |
Since the file IO in main() reads 16K at a time, any file 8K or larger would |
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million |
"a"s). |
I also changed the declaration of variables i & j in SHA1Update to |
unsigned long from unsigned int for the same reason. |
These changes should make no difference to any 32 bit implementations since |
an |
int and a long are the same size in those environments. |
-- |
I also corrected a few compiler warnings generated by Borland C. |
1. Added #include <process.h> for exit() prototype |
2. Removed unused variable 'j' in SHA1Final |
3. Changed exit(0) to return(0) at end of main. |
ALL changes I made can be located by searching for comments containing 'JHB' |
----------------- |
Modified 8/98 |
By Steve Reid <sreid@sea-to-sky.net> |
Still 100% public domain |
1- Removed #include <process.h> and used return() instead of exit() |
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) |
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net |
----------------- |
Modified 4/01 |
By Saul Kravitz <Saul.Kravitz@celera.com> |
Still 100% PD |
Modified to run on Compaq Alpha hardware. |
----------------- |
Modified 07/2002 |
By Ralph Giles <giles@ghostscript.com> |
Still 100% public domain |
modified for use with stdint types, autoconf |
code cleanup, removed attribution comments |
switched SHA1Final() argument order for consistency |
use SHA1_ prefix for public api |
move public api to sha1.h |
*/ |
/* |
Test Vectors (from FIPS PUB 180-1) |
"abc" |
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D |
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" |
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 |
A million repetitions of "a" |
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F |
*/ |
/* #define SHA1HANDSOFF */ |
#ifdef HAVE_CONFIG_H |
#include "config.h" |
#endif |
#include <stdio.h> |
#include <string.h> |
#include "os_types.h" |
#include "sha1.h" |
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]); |
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
/* blk0() and blk() perform the initial expand. */ |
/* I got the idea of expanding during the round function from SSLeay */ |
/* FIXME: can we do this in an endian-proof way? */ |
#ifdef WORDS_BIGENDIAN |
#define blk0(i) block->l[i] |
#else |
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ |
|(rol(block->l[i],8)&0x00FF00FF)) |
#endif |
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ |
^block->l[(i+2)&15]^block->l[i&15],1)) |
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ |
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); |
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); |
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); |
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); |
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); |
#ifdef VERBOSE /* SAK */ |
void SHAPrintContext(SHA1_CTX *context, char *msg){ |
printf("%s (%d,%d) %x %x %x %x %x\n", |
msg, |
context->count[0], context->count[1], |
context->state[0], |
context->state[1], |
context->state[2], |
context->state[3], |
context->state[4]); |
} |
#endif /* VERBOSE */ |
/* Hash a single 512-bit block. This is the core of the algorithm. */ |
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) |
{ |
uint32_t a, b, c, d, e; |
typedef union { |
uint8_t c[64]; |
uint32_t l[16]; |
} CHAR64LONG16; |
CHAR64LONG16* block; |
#ifdef SHA1HANDSOFF |
static uint8_t workspace[64]; |
block = (CHAR64LONG16*)workspace; |
memcpy(block, buffer, 64); |
#else |
block = (CHAR64LONG16*)buffer; |
#endif |
/* Copy context->state[] to working vars */ |
a = state[0]; |
b = state[1]; |
c = state[2]; |
d = state[3]; |
e = state[4]; |
/* 4 rounds of 20 operations each. Loop unrolled. */ |
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); |
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); |
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); |
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); |
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); |
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); |
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); |
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); |
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); |
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); |
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); |
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); |
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); |
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); |
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); |
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); |
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); |
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); |
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); |
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); |
/* Add the working vars back into context.state[] */ |
state[0] += a; |
state[1] += b; |
state[2] += c; |
state[3] += d; |
state[4] += e; |
/* Wipe variables */ |
a = b = c = d = e = 0; |
} |
/* SHA1Init - Initialize new context */ |
void SHA1_Init(SHA1_CTX* context) |
{ |
/* SHA1 initialization constants */ |
context->state[0] = 0x67452301; |
context->state[1] = 0xEFCDAB89; |
context->state[2] = 0x98BADCFE; |
context->state[3] = 0x10325476; |
context->state[4] = 0xC3D2E1F0; |
context->count[0] = context->count[1] = 0; |
} |
/* Run your data through this. */ |
void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len) |
{ |
size_t i, j; |
#ifdef VERBOSE |
SHAPrintContext(context, "before"); |
#endif |
j = (context->count[0] >> 3) & 63; |
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; |
context->count[1] += (len >> 29); |
if ((j + len) > 63) { |
memcpy(&context->buffer[j], data, (i = 64-j)); |
SHA1_Transform(context->state, context->buffer); |
for ( ; i + 63 < len; i += 64) { |
SHA1_Transform(context->state, data + i); |
} |
j = 0; |
} |
else i = 0; |
memcpy(&context->buffer[j], &data[i], len - i); |
#ifdef VERBOSE |
SHAPrintContext(context, "after "); |
#endif |
} |
/* Add padding and return the message digest. */ |
void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE]) |
{ |
uint32_t i; |
uint8_t finalcount[8]; |
for (i = 0; i < 8; i++) { |
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] |
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ |
} |
SHA1_Update(context, (uint8_t *)"\200", 1); |
while ((context->count[0] & 504) != 448) { |
SHA1_Update(context, (uint8_t *)"\0", 1); |
} |
SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ |
for (i = 0; i < SHA1_DIGEST_SIZE; i++) { |
digest[i] = (uint8_t) |
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); |
} |
/* Wipe variables */ |
i = 0; |
memset(context->buffer, 0, 64); |
memset(context->state, 0, 20); |
memset(context->count, 0, 8); |
memset(finalcount, 0, 8); /* SWR */ |
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ |
SHA1_Transform(context->state, context->buffer); |
#endif |
} |
/*************************************************************/ |
#if 0 |
int main(int argc, char** argv) |
{ |
int i, j; |
SHA1_CTX context; |
unsigned char digest[SHA1_DIGEST_SIZE], buffer[16384]; |
FILE* file; |
if (argc > 2) { |
puts("Public domain SHA-1 implementation - by Steve Reid <sreid@sea-to-sky.net>"); |
puts("Modified for 16 bit environments 7/98 - by James H. Brown <jbrown@burgoyne.com>"); /* JHB */ |
puts("Produces the SHA-1 hash of a file, or stdin if no file is specified."); |
return(0); |
} |
if (argc < 2) { |
file = stdin; |
} |
else { |
if (!(file = fopen(argv[1], "rb"))) { |
fputs("Unable to open file.", stderr); |
return(-1); |
} |
} |
SHA1_Init(&context); |
while (!feof(file)) { /* note: what if ferror(file) */ |
i = fread(buffer, 1, 16384, file); |
SHA1_Update(&context, buffer, i); |
} |
SHA1_Final(&context, digest); |
fclose(file); |
for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) { |
for (j = 0; j < 4; j++) { |
printf("%02X", digest[i*4+j]); |
} |
putchar(' '); |
} |
putchar('\n'); |
return(0); /* JHB */ |
} |
#endif |
/* self test */ |
#ifdef TEST |
static char *test_data[] = { |
"abc", |
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", |
"A million repetitions of 'a'"}; |
static char *test_results[] = { |
"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D", |
"84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1", |
"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"}; |
void digest_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], char *output) |
{ |
int i,j; |
char *c = output; |
for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) { |
for (j = 0; j < 4; j++) { |
sprintf(c,"%02X", digest[i*4+j]); |
c += 2; |
} |
sprintf(c, " "); |
c += 1; |
} |
*(c - 1) = '\0'; |
} |
int main(int argc, char** argv) |
{ |
int k; |
SHA1_CTX context; |
uint8_t digest[20]; |
char output[80]; |
fprintf(stdout, "verifying SHA-1 implementation... "); |
for (k = 0; k < 2; k++){ |
SHA1_Init(&context); |
SHA1_Update(&context, (uint8_t*)test_data[k], strlen(test_data[k])); |
SHA1_Final(&context, digest); |
digest_to_hex(digest, output); |
if (strcmp(output, test_results[k])) { |
fprintf(stdout, "FAIL\n"); |
fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[k]); |
fprintf(stderr,"\t%s returned\n", output); |
fprintf(stderr,"\t%s is correct\n", test_results[k]); |
return (1); |
} |
} |
/* million 'a' vector we feed separately */ |
SHA1_Init(&context); |
for (k = 0; k < 1000000; k++) |
SHA1_Update(&context, (uint8_t*)"a", 1); |
SHA1_Final(&context, digest); |
digest_to_hex(digest, output); |
if (strcmp(output, test_results[2])) { |
fprintf(stdout, "FAIL\n"); |
fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[2]); |
fprintf(stderr,"\t%s returned\n", output); |
fprintf(stderr,"\t%s is correct\n", test_results[2]); |
return (1); |
} |
/* success */ |
fprintf(stdout, "ok\n"); |
return(0); |
} |
#endif /* TEST */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/sdk/sources/libjbig2dec/sha1.h |
---|
0,0 → 1,27 |
/* public api for steve reid's public domain SHA-1 implementation */ |
/* this file is in the public domain */ |
#ifndef __SHA1_H |
#define __SHA1_H |
#ifdef __cplusplus |
extern "C" { |
#endif |
typedef struct { |
uint32_t state[5]; |
uint32_t count[2]; |
uint8_t buffer[64]; |
} SHA1_CTX; |
#define SHA1_DIGEST_SIZE 20 |
void SHA1_Init(SHA1_CTX* context); |
void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len); |
void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE]); |
#ifdef __cplusplus |
} |
#endif |
#endif /* __SHA1_H */ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |