diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-07-29 23:17:46 +0000 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-07-29 23:17:46 +0000 |
commit | d797d4707564bd9c0e1536d1d6355945aa1be740 (patch) | |
tree | b6aef992de0ce2aa306c4dd330512852c1a63ede /fitz/filt_dctd.c | |
parent | 0b954421d7908c8b835d96b4a945418c2ae08de7 (diff) | |
download | mupdf-d797d4707564bd9c0e1536d1d6355945aa1be740.tar.xz |
Use chained reader like interface for filters instead of process interface.
Diffstat (limited to 'fitz/filt_dctd.c')
-rw-r--r-- | fitz/filt_dctd.c | 328 |
1 files changed, 143 insertions, 185 deletions
diff --git a/fitz/filt_dctd.c b/fitz/filt_dctd.c index 3b3cc415..e260b34c 100644 --- a/fitz/filt_dctd.c +++ b/fitz/filt_dctd.c @@ -5,254 +5,212 @@ typedef struct fz_dctd_s fz_dctd; -struct myerrmgr +struct fz_dctd_s { - struct jpeg_error_mgr super; + fz_stream *chain; + int colortransform; + int init, done; + unsigned char *scanline; + int stride; + int remain; + struct jpeg_decompress_struct cinfo; + struct jpeg_source_mgr srcmgr; + struct jpeg_error_mgr errmgr; jmp_buf jb; char msg[JMSG_LENGTH_MAX]; }; -static void myerrexit(j_common_ptr cinfo) +static void error_exit(j_common_ptr cinfo) { - struct myerrmgr *err = (struct myerrmgr *)cinfo->err; - char msgbuf[JMSG_LENGTH_MAX]; - err->super.format_message(cinfo, msgbuf); - fz_strlcpy(err->msg, msgbuf, sizeof err->msg); - longjmp(err->jb, 1); + fz_dctd *state = cinfo->client_data; + cinfo->err->format_message(cinfo, state->msg); + longjmp(state->jb, 1); } -static void myoutmess(j_common_ptr cinfo) +static void init_source(j_decompress_ptr cinfo) { - struct myerrmgr *err = (struct myerrmgr *)cinfo->err; - char msgbuf[JMSG_LENGTH_MAX]; - err->super.format_message(cinfo, msgbuf); - fz_warn("jpeg error: %s", msgbuf); + /* nothing to do */ } -static void myiniterr(struct myerrmgr *err) +static void term_source(j_decompress_ptr cinfo) { - jpeg_std_error(&err->super); - err->super.error_exit = myerrexit; - err->super.output_message = myoutmess; + /* nothing to do */ } -struct mysrcmgr +static boolean fill_input_buffer(j_decompress_ptr cinfo) { - struct jpeg_source_mgr super; - fz_buffer *buf; - int skip; -}; + struct jpeg_source_mgr *src = cinfo->src; + fz_dctd *state = cinfo->client_data; + fz_stream *chain = state->chain; -struct fz_dctd_s -{ - fz_filter super; - struct jpeg_decompress_struct cinfo; - struct mysrcmgr src; - struct myerrmgr err; - int colortransform; - int stage; -}; + if (chain->rp == chain->wp) + fz_fillbuffer(chain); -static void myinitsource(j_decompress_ptr cinfo) { /* empty */ } -static int myfillinput(j_decompress_ptr cinfo) { return FALSE; } -static void mytermsource(j_decompress_ptr cinfo) { /* empty */ } - -static void myskipinput(j_decompress_ptr cinfo, long n) -{ - struct mysrcmgr *src = (struct mysrcmgr *)cinfo->src; - fz_buffer *in = src->buf; + src->next_input_byte = chain->rp; + src->bytes_in_buffer = chain->wp - chain->rp; + chain->rp = chain->wp; - assert(src->skip == 0); - - in->rp = in->wp - src->super.bytes_in_buffer; - - if (in->rp + n > in->wp) { - src->skip = (in->rp + n) - in->wp; - in->rp = in->wp; - } - else { - src->skip = 0; - in->rp += n; - } - - src->super.bytes_in_buffer = in->wp - in->rp; - src->super.next_input_byte = in->rp; -} - -fz_filter * -fz_newdctd(fz_obj *params) -{ - fz_obj *obj; - int colortransform; - - FZ_NEWFILTER(fz_dctd, d, dctd); - - colortransform = -1; /* "unset" */ - - if (params) + if (src->bytes_in_buffer == 0) { - obj = fz_dictgets(params, "ColorTransform"); - if (obj) - colortransform = fz_toint(obj); + static unsigned char eoi[2] = { 0xFF, JPEG_EOI }; + fz_warn("premature end of file in jpeg"); + src->next_input_byte = eoi; + src->bytes_in_buffer = 2; } - d->colortransform = colortransform; - d->stage = 0; - - /* setup error callback first thing */ - myiniterr(&d->err); - d->cinfo.err = (struct jpeg_error_mgr*) &d->err; - - if (setjmp(d->err.jb)) - fz_warn("cannot initialise jpeg: %s", d->err.msg); - - /* create decompression object. this zeroes cinfo except for err. */ - jpeg_create_decompress(&d->cinfo); - - /* prepare source manager */ - d->cinfo.src = (struct jpeg_source_mgr *)&d->src; - d->src.super.init_source = myinitsource; - d->src.super.fill_input_buffer = myfillinput; - d->src.super.skip_input_data = myskipinput; - d->src.super.resync_to_restart = jpeg_resync_to_restart; - d->src.super.term_source = mytermsource; - - d->src.super.bytes_in_buffer = 0; - d->src.super.next_input_byte = nil; - d->src.skip = 0; - - return (fz_filter *)d; + return 1; } -void -fz_dropdctd(fz_filter *filter) +static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - fz_dctd *d = (fz_dctd*)filter; - if (setjmp(d->err.jb)) { - fz_warn("jpeg error: jpeg_destroy_decompress: %s", d->err.msg); - return; + struct jpeg_source_mgr *src = cinfo->src; + if (num_bytes > 0) + { + while (num_bytes > src->bytes_in_buffer) + { + num_bytes -= src->bytes_in_buffer; + (void) src->fill_input_buffer(cinfo); + } + src->next_input_byte += num_bytes; + src->bytes_in_buffer -= num_bytes; } - jpeg_destroy_decompress(&d->cinfo); } -fz_error -fz_processdctd(fz_filter *filter, fz_buffer *in, fz_buffer *out) +static int +readdctd(fz_stream *stm, unsigned char *buf, int len) { - fz_dctd *d = (fz_dctd*)filter; - int b; - int i; - int stride; - JSAMPROW scanlines[1]; - - d->src.buf = in; + fz_dctd *state = stm->state; + j_decompress_ptr cinfo = &state->cinfo; + unsigned char *p = buf; - /* skip any bytes left over from myskipinput() */ - if (d->src.skip > 0) { - if (in->rp + d->src.skip > in->wp) { - d->src.skip = (in->rp + d->src.skip) - in->wp; - in->rp = in->wp; - goto needinput; - } - else { - in->rp += d->src.skip; - d->src.skip = 0; - } - } - - d->src.super.bytes_in_buffer = in->wp - in->rp; - d->src.super.next_input_byte = in->rp; - - if (setjmp(d->err.jb)) + if (setjmp(state->jb)) { - return fz_throw("cannot decode jpeg: %s", d->err.msg); + state->done = 1; + return fz_throw("jpeg error: %s", state->msg); } - switch (d->stage) + if (!state->init) { - case 0: - i = jpeg_read_header(&d->cinfo, TRUE); - if (i == JPEG_SUSPENDED) - goto needinput; + cinfo->client_data = state; + cinfo->err = &state->errmgr; + jpeg_std_error(cinfo->err); + cinfo->err->error_exit = error_exit; + jpeg_create_decompress(cinfo); + + cinfo->src = &state->srcmgr; + cinfo->src->init_source = init_source; + cinfo->src->fill_input_buffer = fill_input_buffer; + cinfo->src->skip_input_data = skip_input_data; + cinfo->src->resync_to_restart = jpeg_resync_to_restart; + cinfo->src->term_source = term_source; + cinfo->src->next_input_byte = state->chain->rp; + cinfo->src->bytes_in_buffer = 0; + + jpeg_read_header(cinfo, 1); /* speed up jpeg decoding a bit */ - d->cinfo.dct_method = JDCT_FASTEST; - d->cinfo.do_fancy_upsampling = FALSE; + cinfo->dct_method = JDCT_FASTEST; + cinfo->do_fancy_upsampling = FALSE; /* default value if ColorTransform is not set */ - if (d->colortransform == -1) + if (state->colortransform == -1) { - if (d->cinfo.num_components == 3) - d->colortransform = 1; + if (state->cinfo.num_components == 3) + state->colortransform = 1; else - d->colortransform = 0; + state->colortransform = 0; } - if (d->cinfo.saw_Adobe_marker) - d->colortransform = d->cinfo.Adobe_transform; + if (cinfo->saw_Adobe_marker) + state->colortransform = cinfo->Adobe_transform; /* Guess the input colorspace, and set output colorspace accordingly */ - switch (d->cinfo.num_components) + switch (cinfo->num_components) { case 3: - if (d->colortransform) - d->cinfo.jpeg_color_space = JCS_YCbCr; + if (state->colortransform) + cinfo->jpeg_color_space = JCS_YCbCr; else - d->cinfo.jpeg_color_space = JCS_RGB; + cinfo->jpeg_color_space = JCS_RGB; break; case 4: - if (d->colortransform) - d->cinfo.jpeg_color_space = JCS_YCCK; + if (state->colortransform) + cinfo->jpeg_color_space = JCS_YCCK; else - d->cinfo.jpeg_color_space = JCS_CMYK; + cinfo->jpeg_color_space = JCS_CMYK; break; } - /* fall through */ - d->stage = 1; + jpeg_start_decompress(cinfo); + + state->stride = cinfo->output_width * cinfo->output_components; + state->remain = 0; + state->scanline = fz_malloc(state->stride); - case 1: - b = jpeg_start_decompress(&d->cinfo); - if (b == FALSE) - goto needinput; + state->init = 1; + } - /* fall through */ - d->stage = 2; + while (state->remain > 0 && p < buf + len) + *p++ = state->scanline[state->stride - state->remain--]; - case 2: - stride = d->cinfo.output_width * d->cinfo.output_components; + while (p < buf + len) + { + if (state->done) + return p - buf; - while (d->cinfo.output_scanline < d->cinfo.output_height) + if (cinfo->output_scanline == cinfo->output_height) { - if (out->wp + stride > out->ep) - goto needoutput; + state->done = 1; + jpeg_finish_decompress(cinfo); + jpeg_destroy_decompress(cinfo); + return p - buf; + } - scanlines[0] = out->wp; + if (p + state->stride <= buf + len) + { + jpeg_read_scanlines(cinfo, &p, 1); + p += state->stride; + } + else + { + jpeg_read_scanlines(cinfo, &state->scanline, 1); + state->remain = state->stride; + } - i = jpeg_read_scanlines(&d->cinfo, scanlines, 1); + while (state->remain > 0 && p < buf + len) + *p++ = state->scanline[state->stride - state->remain--]; + } - if (i == 0) - goto needinput; + return p - buf; +} - out->wp += stride; - } +static void +closedctd(fz_stream *stm) +{ + fz_dctd *state = stm->state; + fz_free(state->scanline); + fz_close(state->chain); + fz_free(state); +} - /* fall through */ - d->stage = 3; +fz_stream * +fz_opendctd(fz_stream *chain, fz_obj *params) +{ + fz_dctd *state; + fz_obj *obj; - case 3: - b = jpeg_finish_decompress(&d->cinfo); - if (b == FALSE) - goto needinput; - d->stage = 4; - in->rp = in->wp - d->src.super.bytes_in_buffer; - return fz_iodone; - } + state = fz_malloc(sizeof(fz_dctd)); + state->chain = chain; + state->colortransform = -1; /* unset */ + state->init = 0; + state->done = 0; + state->scanline = nil; + state->stride = 0; + state->remain = 0; -needinput: - in->rp = in->wp - d->src.super.bytes_in_buffer; - return fz_ioneedin; + obj = fz_dictgets(params, "ColorTransform"); + if (obj) + state->colortransform = fz_toint(obj); -needoutput: - in->rp = in->wp - d->src.super.bytes_in_buffer; - return fz_ioneedout; + return fz_newstream(state, readdctd, closedctd); } |