1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
4 This software is provided AS-IS with no warranty, either express or
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
32 #include "jbig2_priv.h"
35 jbig2_default_alloc (Jbig2Allocator *allocator, size_t size)
41 jbig2_default_free (Jbig2Allocator *allocator, void *p)
47 jbig2_default_realloc (Jbig2Allocator *allocator, void *p, size_t size)
49 return realloc (p, size);
52 static Jbig2Allocator jbig2_default_allocator =
60 jbig2_alloc (Jbig2Allocator *allocator, size_t size, size_t num)
62 /* check for integer multiplication overflow */
63 if (num > 0 && size >= (size_t)-0x100 / num)
65 return allocator->alloc(allocator, size * num);
69 jbig2_free (Jbig2Allocator *allocator, void *p)
71 allocator->free (allocator, p);
75 jbig2_realloc (Jbig2Allocator *allocator, void *p, size_t size, size_t num)
77 /* check for integer multiplication overflow */
78 if (num > 0 && size >= (size_t)-0x100 / num)
80 return allocator->realloc(allocator, p, size * num);
84 jbig2_default_error(void *data, const char *msg,
85 Jbig2Severity severity, int32_t seg_idx)
87 /* report only fatal errors by default */
88 if (severity == JBIG2_SEVERITY_FATAL) {
89 fprintf(stderr, "jbig2 decoder FATAL ERROR: %s", msg);
90 if (seg_idx != -1) fprintf(stderr, " (segment 0x%02x)", seg_idx);
91 fprintf(stderr, "\n");
99 jbig2_error(Jbig2Ctx *ctx, Jbig2Severity severity, int32_t segment_number,
100 const char *fmt, ...)
108 n = vsnprintf (buf, sizeof(buf), fmt, ap);
110 if (n < 0 || n == sizeof(buf))
111 strncpy (buf, "jbig2_error: error in generating error string", sizeof(buf));
112 code = ctx->error_callback (ctx->error_callback_data, buf, severity, segment_number);
113 if (severity == JBIG2_SEVERITY_FATAL)
119 jbig2_ctx_new (Jbig2Allocator *allocator,
120 Jbig2Options options,
121 Jbig2GlobalCtx *global_ctx,
122 Jbig2ErrorCallback error_callback,
123 void *error_callback_data)
127 if (allocator == NULL)
128 allocator = &jbig2_default_allocator;
129 if (error_callback == NULL)
130 error_callback = &jbig2_default_error;
132 result = (Jbig2Ctx*)jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
133 if (result == NULL) {
134 error_callback(error_callback_data, "initial context allocation failed!",
135 JBIG2_SEVERITY_FATAL, -1);
139 result->allocator = allocator;
140 result->options = options;
141 result->global_ctx = (const Jbig2Ctx *)global_ctx;
142 result->error_callback = error_callback;
143 result->error_callback_data = error_callback_data;
145 result->state = (options & JBIG2_OPTIONS_EMBEDDED) ?
146 JBIG2_FILE_SEQUENTIAL_HEADER :
151 result->n_segments = 0;
152 result->n_segments_max = 16;
153 result->segments = jbig2_new(result, Jbig2Segment*, result->n_segments_max);
154 if (result->segments == NULL) {
155 error_callback(error_callback_data, "initial segments allocation failed!",
156 JBIG2_SEVERITY_FATAL, -1);
157 jbig2_free(allocator, result);
160 result->segment_index = 0;
162 result->current_page = 0;
163 result->max_page_index = 4;
164 result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
165 if (result->pages == NULL) {
166 error_callback(error_callback_data, "initial pages allocation failed!",
167 JBIG2_SEVERITY_FATAL, -1);
168 jbig2_free(allocator, result->segments);
169 jbig2_free(allocator, result);
174 for (index = 0; index < result->max_page_index; index++) {
175 result->pages[index].state = JBIG2_PAGE_FREE;
176 result->pages[index].number = 0;
177 result->pages[index].image = NULL;
184 #define get_uint16(bptr)\
185 (((bptr)[0] << 8) | (bptr)[1])
186 #define get_int16(bptr)\
187 (((int)get_uint16(bptr) ^ 0x8000) - 0x8000)
190 jbig2_get_int16(const byte *bptr)
192 return get_int16(bptr);
196 jbig2_get_uint16(const byte *bptr)
198 return get_uint16(bptr);
202 jbig2_get_int32(const byte *bptr)
204 return ((int32_t)get_int16(bptr) << 16) | get_uint16(bptr + 2);
208 jbig2_get_uint32(const byte *bptr)
210 return ((uint32_t)get_uint16(bptr) << 16) | get_uint16(bptr + 2);
215 * jbig2_data_in: submit data for decoding
216 * @ctx: The jbig2dec decoder context
217 * @data: a pointer to the data buffer
218 * @size: the size of the data buffer in bytes
220 * Copies the specified data into internal storage and attempts
221 * to (continue to) parse it as part of a jbig2 data stream.
223 * Return code: 0 on success
224 * -1 if there is a parsing error, or whatever
225 * the error handling callback returns
228 jbig2_data_in (Jbig2Ctx *ctx, const unsigned char *data, size_t size)
230 const size_t initial_buf_size = 1024;
232 if (ctx->buf == NULL)
234 size_t buf_size = initial_buf_size;
238 while (buf_size < size);
239 ctx->buf = jbig2_new(ctx, byte, buf_size);
240 if (ctx->buf == NULL)
242 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
243 "failed to allocate ctx->buf in jbig2_data_in");
245 ctx->buf_size = buf_size;
249 else if (ctx->buf_wr_ix + size > ctx->buf_size)
251 if (ctx->buf_rd_ix <= (ctx->buf_size >> 1) &&
252 ctx->buf_wr_ix - ctx->buf_rd_ix + size <= ctx->buf_size)
254 memmove(ctx->buf, ctx->buf + ctx->buf_rd_ix,
255 ctx->buf_wr_ix - ctx->buf_rd_ix);
260 size_t buf_size = initial_buf_size;
264 while (buf_size < ctx->buf_wr_ix - ctx->buf_rd_ix + size);
265 buf = jbig2_new(ctx, byte, buf_size);
268 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
269 "failed to allocate buf in jbig2_data_in");
271 memcpy(buf, ctx->buf + ctx->buf_rd_ix,
272 ctx->buf_wr_ix - ctx->buf_rd_ix);
273 jbig2_free(ctx->allocator, ctx->buf);
275 ctx->buf_size = buf_size;
277 ctx->buf_wr_ix -= ctx->buf_rd_ix;
280 memcpy(ctx->buf + ctx->buf_wr_ix, data, size);
281 ctx->buf_wr_ix += size;
283 /* data has now been added to buffer */
287 const byte jbig2_id_string[8] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a };
288 Jbig2Segment *segment;
294 case JBIG2_FILE_HEADER:
296 if (ctx->buf_wr_ix - ctx->buf_rd_ix < 9)
298 if (memcmp(ctx->buf + ctx->buf_rd_ix, jbig2_id_string, 8))
299 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
300 "Not a JBIG2 file header");
302 ctx->file_header_flags = ctx->buf[ctx->buf_rd_ix + 8];
303 if (ctx->file_header_flags & 0xFC) {
304 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
305 "reserved bits (2-7) of file header flags are not zero (0x%02x)", ctx->file_header_flags);
308 if (!(ctx->file_header_flags & 2)) /* number of pages is known */
310 if (ctx->buf_wr_ix - ctx->buf_rd_ix < 13)
312 ctx->n_pages = jbig2_get_uint32(ctx->buf + ctx->buf_rd_ix + 9);
313 ctx->buf_rd_ix += 13;
314 if (ctx->n_pages == 1)
315 jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a single page document");
317 jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a %d page document", ctx->n_pages);
319 else /* number of pages not known */
324 /* determine the file organization based on the flags - D.4.2 again */
325 if (ctx->file_header_flags & 1)
327 ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
328 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates sequential organization");
332 ctx->state = JBIG2_FILE_RANDOM_HEADERS;
333 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates random-access organization");
337 case JBIG2_FILE_SEQUENTIAL_HEADER:
338 case JBIG2_FILE_RANDOM_HEADERS:
339 segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix,
340 ctx->buf_wr_ix - ctx->buf_rd_ix,
343 return 0; /* need more data */
344 ctx->buf_rd_ix += header_size;
346 if (ctx->n_segments == ctx->n_segments_max)
347 ctx->segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment*,
348 (ctx->n_segments_max <<= 2));
350 ctx->segments[ctx->n_segments++] = segment;
351 if (ctx->state == JBIG2_FILE_RANDOM_HEADERS)
353 if ((segment->flags & 63) == 51) /* end of file */
354 ctx->state = JBIG2_FILE_RANDOM_BODIES;
356 else /* JBIG2_FILE_SEQUENTIAL_HEADER */
357 ctx->state = JBIG2_FILE_SEQUENTIAL_BODY;
359 case JBIG2_FILE_SEQUENTIAL_BODY:
360 case JBIG2_FILE_RANDOM_BODIES:
361 segment = ctx->segments[ctx->segment_index];
362 if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
363 return 0; /* need more data */
364 code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
365 ctx->buf_rd_ix += segment->data_length;
366 ctx->segment_index++;
367 if (ctx->state == JBIG2_FILE_RANDOM_BODIES)
369 if (ctx->segment_index == ctx->n_segments)
370 ctx->state = JBIG2_FILE_EOF;
372 else /* JBIG2_FILE_SEQUENCIAL_BODY */
374 ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
378 ctx->state = JBIG2_FILE_EOF;
383 if (ctx->buf_rd_ix == ctx->buf_wr_ix)
385 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
386 "Garbage beyond end of file");
392 jbig2_ctx_free (Jbig2Ctx *ctx)
394 Jbig2Allocator *ca = ctx->allocator;
397 jbig2_free(ca, ctx->buf);
398 if (ctx->segments != NULL) {
399 for (i = 0; i < ctx->n_segments; i++)
400 jbig2_free_segment(ctx, ctx->segments[i]);
401 jbig2_free(ca, ctx->segments);
404 if (ctx->pages != NULL) {
405 for (i = 0; i <= ctx->current_page; i++)
406 if (ctx->pages[i].image != NULL)
407 jbig2_image_release(ctx, ctx->pages[i].image);
408 jbig2_free(ca, ctx->pages);
414 Jbig2GlobalCtx *jbig2_make_global_ctx (Jbig2Ctx *ctx)
416 return (Jbig2GlobalCtx *)ctx;
419 void jbig2_global_ctx_free(Jbig2GlobalCtx *global_ctx)
421 jbig2_ctx_free((Jbig2Ctx *)global_ctx);
425 /* I'm not committed to keeping the word stream interface. It's handy
426 when you think you may be streaming your input, but if you're not
427 (as is currently the case), it just adds complexity.
431 Jbig2WordStream super;
434 } Jbig2WordStreamBuf;
437 jbig2_word_stream_buf_get_next_word(Jbig2WordStream *self, int offset,
440 Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *)self;
441 const byte *data = z->data;
444 if (offset + 4 < z->size)
445 result = (data[offset] << 24) | (data[offset + 1] << 16) |
446 (data[offset + 2] << 8) | data[offset + 3];
447 else if (offset >= z->size)
454 for (i = 0; i < z->size - offset; i++)
455 result |= data[offset + i] << ((3 - i) << 3);
462 jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size)
464 Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
467 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
468 "failed to allocate Jbig2WordStreamBuf in jbig2_word_stream_buf_new");
472 result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
476 return &result->super;
480 jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws)
482 jbig2_free(ctx->allocator, ws);