fz_error * fz_processjbig2d(fz_filter *filter, fz_buffer *in, fz_buffer *out) { fz_jbig2d *d = (fz_jbig2d*)filter; int len; int i; while (1) { if (in->rp == in->wp) { if (!in->eof) return fz_ioneedin; if (!d->page) { jbig2_complete_page(d->ctx); d->page = jbig2_page_out(d->ctx); } if (out->wp == out->ep) return fz_ioneedout; len = out->ep - out->wp; if (d->idx + len > d->page->height * d->page->stride) len = d->page->height * d->page->stride - d->idx; /* XXX memcpy(out->wp, d->page->data + d->idx, len); */ { unsigned char * restrict in = &d->page->data[d->idx]; unsigned char * restrict o = out->wp; for (i = 0; i < len; i++) *o++ = 0xff ^ *in++; } out->wp += len; d->idx += len; if (d->idx == d->page->height * d->page->stride) { jbig2_release_page(d->ctx, d->page); out->eof = 1; return fz_iodone; } } else { len = in->wp - in->rp; jbig2_data_in(d->ctx, in->rp, len); in->rp += len; } }
/* process a section of the input and return any decoded data. see strimpl.h for return codes. */ static int s_jbig2decode_process(stream_state * ss, stream_cursor_read * pr, stream_cursor_write * pw, bool last) { stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss; Jbig2Image *image = state->image; long in_size = pr->limit - pr->ptr; long out_size = pw->limit - pw->ptr; int status = 0; /* there will only be a single page image, so pass all data in before looking for any output. note that the gs stream library expects offset-by-one indexing of the buffers, while jbig2dec uses normal 0 indexes */ if (in_size > 0) { /* pass all available input to the decoder */ jbig2_data_in(state->decode_ctx, pr->ptr + 1, in_size); pr->ptr += in_size; /* simulate end-of-page segment */ if (last == 1) { jbig2_complete_page(state->decode_ctx); } /* handle fatal decoding errors reported through our callback */ if (state->error) return state->error; } if (out_size > 0) { if (image == NULL) { /* see if a page image in available */ image = jbig2_page_out(state->decode_ctx); if (image != NULL) { state->image = image; state->offset = 0; } } if (image != NULL) { /* copy data out of the decoded image, if any */ long image_size = image->height*image->stride; long usable = min(image_size - state->offset, out_size); memcpy(pw->ptr + 1, image->data + state->offset, usable); s_jbig2decode_invert_buffer(pw->ptr + 1, usable); state->offset += usable; pw->ptr += usable; status = (state->offset < image_size) ? 1 : 0; } } return status; }
int read_jbig2d(fz_stream *stm, unsigned char *buf, int len) { fz_jbig2d *state = (fz_jbig2d *)stm->state; unsigned char tmp[4096]; unsigned char *p = buf; unsigned char *ep = buf + len; unsigned char *s; int x, w, n; //try{ if (!state->page) { while (1) { n = fz_read(state->chain, tmp, sizeof tmp); if (n == 0) break; jbig2_data_in(state->ctx, tmp, n); } jbig2_complete_page(state->ctx); state->page = jbig2_page_out(state->ctx); if (!state->page) return 0; //throw("jbig2_page_out failed"); } s = state->page->data; w = state->page->height * state->page->stride; x = state->idx; while (p < ep && x < w) *p++ = s[x++] ^ 0xff; state->idx = x; return p - buf; /*} catch(...){ return -1; }*/ }
/** * 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; }
static int read_jbig2d(fz_stream *stm, unsigned char *buf, int len) { fz_jbig2d *state = stm->state; unsigned char tmp[4096]; unsigned char *p = buf; unsigned char *ep = buf + len; unsigned char *s; int x, w, n; if (!state->page) { while (1) { n = fz_read(state->chain, tmp, sizeof tmp); if (n < 0) return fz_rethrow(n, "read error in jbig2 filter"); if (n == 0) break; jbig2_data_in(state->ctx, tmp, n); } jbig2_complete_page(state->ctx); state->page = jbig2_page_out(state->ctx); if (!state->page) return fz_throw("jbig2_page_out failed"); } s = state->page->data; w = state->page->height * state->page->stride; x = state->idx; while (p < ep && x < w) *p++ = s[x++] ^ 0xff; state->idx = x; return p - buf; }
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; jbig2_data_in(ctx, buf, n_bytes); } 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; jbig2_data_in(ctx, buf, n_bytes); } 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; }