123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830 |
- /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
-
- 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 more information about licensing, please refer to
- http://www.ghostscript.com/licensing/. For information on
- commercial licensing, go to http://www.artifex.com/licensing/ or
- contact Artifex Software, Inc., 101 Lucas Valley Road #110,
- San Rafael, CA 94903, U.S.A., +1(415)492-9861.
- */
- /* $Id: scfd.c,v 1.9 2005/09/21 03:24:16 ray Exp $ */
- /* CCITTFax decoding filter */
- #include "stdio_.h" /* includes std.h */
- #include "memory_.h"
- #include "gdebug.h"
- #include "strimpl.h"
- #include "scf.h"
- #include "scfx.h"
- /* ------ CCITTFaxDecode ------ */
- private_st_CFD_state();
- /* Set default parameter values. */
- private void
- s_CFD_set_defaults(register stream_state * st)
- {
- stream_CFD_state *const ss = (stream_CFD_state *) st;
- s_CFD_set_defaults_inline(ss);
- }
- /* Initialize CCITTFaxDecode filter */
- private int
- s_CFD_init(stream_state * st)
- {
- stream_CFD_state *const ss = (stream_CFD_state *) st;
- int raster = ss->raster =
- ROUND_UP((ss->Columns + 7) >> 3, ss->DecodedByteAlign);
- byte white = (ss->BlackIs1 ? 0 : 0xff);
- s_hcd_init_inline(ss);
- /* Because skip_white_pixels can look as many as 4 bytes ahead, */
- /* we need to allow 4 extra bytes at the end of the row buffers. */
- ss->lbuf = gs_alloc_bytes(st->memory, raster + 4, "CFD lbuf");
- ss->lprev = 0;
- if (ss->lbuf == 0)
- return ERRC;
- /****** WRONG ******/
- if (ss->K != 0) {
- ss->lprev = gs_alloc_bytes(st->memory, raster + 4, "CFD lprev");
- if (ss->lprev == 0)
- return ERRC;
- /****** WRONG ******/
- /* Clear the initial reference line for 2-D encoding. */
- memset(ss->lbuf, white, raster);
- /* Ensure that the scan of the reference line will stop. */
- ss->lbuf[raster] = 0xa0;
- }
- ss->k_left = min(ss->K, 0);
- ss->run_color = 0;
- ss->damaged_rows = 0;
- ss->skipping_damage = false;
- ss->cbit = 0;
- ss->uncomp_run = 0;
- ss->rows_left = (ss->Rows <= 0 || ss->EndOfBlock ? -1 : ss->Rows + 1);
- ss->row = 0;
- ss->rpos = ss->wpos = raster - 1;
- ss->eol_count = 0;
- ss->invert = white;
- ss->min_left = 1;
- return 0;
- }
- /* Release the filter. */
- private void
- s_CFD_release(stream_state * st)
- {
- stream_CFD_state *const ss = (stream_CFD_state *) st;
- gs_free_object(st->memory, ss->lprev, "CFD lprev(close)");
- gs_free_object(st->memory, ss->lbuf, "CFD lbuf(close)");
- }
- /* Declare the variables that hold the state. */
- #define cfd_declare_state\
- hcd_declare_state;\
- register byte *q;\
- int qbit
- /* Load the state from the stream. */
- #define cfd_load_state()\
- hcd_load_state(),\
- q = ss->lbuf + ss->wpos, qbit = ss->cbit
- /* Store the state back in the stream. */
- #define cfd_store_state()\
- hcd_store_state(),\
- ss->wpos = q - ss->lbuf, ss->cbit = qbit
- /* Macros to get blocks of bits from the input stream. */
- /* Invariants: 0 <= bits_left <= bits_size; */
- /* bits [bits_left-1..0] contain valid data. */
- #define avail_bits(n) hcd_bits_available(n)
- #define ensure_bits(n, outl) hcd_ensure_bits(n, outl)
- #define peek_bits(n) hcd_peek_bits(n)
- #define peek_var_bits(n) hcd_peek_var_bits(n)
- #define skip_bits(n) hcd_skip_bits(n)
- /* Get a run from the stream. */
- #ifdef DEBUG
- # define IF_DEBUG(expr) expr
- #else
- # define IF_DEBUG(expr) DO_NOTHING
- #endif
- #define get_run(decode, initial_bits, min_bits, runlen, str, locl, outl)\
- BEGIN\
- const cfd_node *np;\
- int clen;\
- \
- HCD_ENSURE_BITS_ELSE(initial_bits) {\
- /* We might still have enough bits for the specific code. */\
- if (bits_left < min_bits) goto outl;\
- np = &decode[hcd_peek_bits_left() << (initial_bits - bits_left)];\
- if ((clen = np->code_length) > bits_left) goto outl;\
- goto locl;\
- }\
- np = &decode[peek_bits(initial_bits)];\
- if ((clen = np->code_length) > initial_bits) {\
- IF_DEBUG(uint init_bits = peek_bits(initial_bits));\
- if (!avail_bits(clen)) goto outl;\
- clen -= initial_bits;\
- skip_bits(initial_bits);\
- ensure_bits(clen, outl); /* can't goto outl */\
- np = &decode[np->run_length + peek_var_bits(clen)];\
- if_debug4('W', "%s xcode=0x%x,%d rlen=%d\n", str,\
- (init_bits << np->code_length) +\
- peek_var_bits(np->code_length),\
- initial_bits + np->code_length,\
- np->run_length);\
- skip_bits(np->code_length);\
- } else {\
- locl: if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,\
- peek_var_bits(clen), clen, np->run_length);\
- skip_bits(clen);\
- }\
- runlen = np->run_length;\
- END
- /* Skip data bits for a white run. */
- /* rlen is either less than 64, or a multiple of 64. */
- #define skip_data(rlen, makeup_label)\
- if ( (qbit -= rlen) < 0 )\
- { q -= qbit >> 3, qbit &= 7;\
- if ( rlen >= 64 ) goto makeup_label;\
- }
- /* Invert data bits for a black run. */
- /* If rlen >= 64, execute makeup_action: this is to handle */
- /* makeup codes efficiently, since these are always a multiple of 64. */
- #define invert_data(rlen, black_byte, makeup_action, d)\
- if ( rlen > qbit )\
- { *q++ ^= (1 << qbit) - 1;\
- rlen -= qbit;\
- switch ( rlen >> 3 )\
- {\
- case 7: /* original rlen possibly >= 64 */\
- if ( rlen + qbit >= 64 ) goto d;\
- *q++ = black_byte;\
- case 6: *q++ = black_byte;\
- case 5: *q++ = black_byte;\
- case 4: *q++ = black_byte;\
- case 3: *q++ = black_byte;\
- case 2: *q++ = black_byte;\
- case 1: *q = black_byte;\
- rlen &= 7;\
- if ( !rlen ) { qbit = 0; break; }\
- q++;\
- case 0: /* know rlen != 0 */\
- qbit = 8 - rlen;\
- *q ^= 0xff << qbit;\
- break;\
- default: /* original rlen >= 64 */\
- d: memset(q, black_byte, rlen >> 3);\
- q += rlen >> 3;\
- rlen &= 7;\
- if ( !rlen ) qbit = 0, q--;\
- else qbit = 8 - rlen, *q ^= 0xff << qbit;\
- makeup_action;\
- }\
- }\
- else\
- qbit -= rlen,\
- *q ^= ((1 << rlen) - 1) << qbit
- /* Buffer refill for CCITTFaxDecode filter */
- private int cf_decode_eol(stream_CFD_state *, stream_cursor_read *);
- private int cf_decode_1d(stream_CFD_state *, stream_cursor_read *);
- private int cf_decode_2d(stream_CFD_state *, stream_cursor_read *);
- private int cf_decode_uncompressed(stream_CFD_state *, stream_cursor_read *);
- private int
- s_CFD_process(stream_state * st, stream_cursor_read * pr,
- stream_cursor_write * pw, bool last)
- {
- stream_CFD_state *const ss = (stream_CFD_state *) st;
- int wstop = ss->raster - 1;
- int eol_count = ss->eol_count;
- int k_left = ss->k_left;
- int rows_left = ss->rows_left;
- int status = 0;
- #ifdef DEBUG
- const byte *rstart = pr->ptr;
- const byte *wstart = pw->ptr;
- #endif
- top:
- #ifdef DEBUG
- {
- hcd_declare_state;
- hcd_load_state();
- if_debug8('w', "[w]CFD_process top: eol_count=%d, k_left=%d, rows_left=%d\n"
- " bits=0x%lx, bits_left=%d, read %u, wrote %u%s\n",
- eol_count, k_left, rows_left,
- (ulong) bits, bits_left,
- (uint) (p - rstart), (uint) (pw->ptr - wstart),
- (ss->skipping_damage ? ", skipping damage" : ""));
- }
- #endif
- if (ss->skipping_damage) { /* Skip until we reach an EOL. */
- hcd_declare_state;
- int skip;
- status = 0;
- do {
- switch ((skip = cf_decode_eol(ss, pr))) {
- default: /* not EOL */
- hcd_load_state();
- skip_bits(-skip);
- hcd_store_state();
- continue;
- case 0: /* need more input */
- goto out;
- case 1: /* EOL */
- { /* Back up over the EOL. */
- hcd_load_state();
- bits_left += run_eol_code_length;
- hcd_store_state();
- }
- ss->skipping_damage = false;
- }
- }
- while (ss->skipping_damage);
- ss->damaged_rows++;
- }
- /*
- * Check for a completed input scan line. This isn't quite as
- * simple as it seems, because we could have run out of input data
- * between a makeup code and a 0-length termination code, or in a
- * 2-D line before a final horizontal code with a 0-length second
- * run. There's probably a way to think about this situation that
- * doesn't require a special check, but I haven't found it yet.
- */
- if (ss->wpos == wstop && ss->cbit <= (-ss->Columns & 7) &&
- (k_left == 0 ? !(ss->run_color & ~1) : ss->run_color == 0)
- ) { /* Check for completed data to be copied to the client. */
- /* (We could avoid the extra copy step for 1-D, but */
- /* it's simpler not to, and it doesn't cost much.) */
- if (ss->rpos < ss->wpos) {
- stream_cursor_read cr;
- cr.ptr = ss->lbuf + ss->rpos;
- cr.limit = ss->lbuf + ss->wpos;
- status = stream_move(&cr, pw);
- ss->rpos = cr.ptr - ss->lbuf;
- if (status)
- goto out;
- }
- ss->row++;
- if (rows_left > 0 && --rows_left == 0)
- goto ck_eol; /* handle EOD if it is present */
- if (ss->K != 0) {
- byte *prev_bits = ss->lprev;
- ss->lprev = ss->lbuf;
- ss->lbuf = prev_bits;
- if (ss->K > 0)
- k_left = (k_left == 0 ? ss->K : k_left) - 1;
- }
- ss->rpos = ss->wpos = -1;
- ss->eol_count = eol_count = 0;
- ss->cbit = 0;
- ss->invert = (ss->BlackIs1 ? 0 : 0xff);
- memset(ss->lbuf, ss->invert, wstop + 1);
- ss->run_color = 0;
- /*
- * If EndOfLine is true, we want to include the byte padding
- * in the string of initial zeros in the EOL. If EndOfLine
- * is false, we aren't sure what we should do....
- */
- if (ss->EncodedByteAlign & !ss->EndOfLine)
- ss->bits_left &= ~7;
- }
- /* If we're between scan lines, scan for EOLs. */
- if (ss->wpos < 0) {
- /*
- * According to Adobe, the decoder should always check for
- * the EOD sequence, regardless of EndOfBlock: the Red Book's
- * documentation of EndOfBlock is wrong.
- */
- ck_eol:
- while ((status = cf_decode_eol(ss, pr)) > 0) {
- if_debug0('w', "[w]EOL\n");
- /* If we are in a Group 3 mixed regime, */
- /* check the next bit for 1- vs. 2-D. */
- if (ss->K > 0) {
- hcd_declare_state;
- hcd_load_state();
- ensure_bits(1, out); /* can't fail */
- k_left = (peek_bits(1) ? 0 : 1);
- skip_bits(1);
- hcd_store_state();
- }
- ++eol_count;
- if (eol_count == (ss->K < 0 ? 2 : 6)) {
- status = EOFC;
- goto out;
- }
- }
- if (rows_left == 0) {
- status = EOFC;
- goto out;
- }
- if (status == 0) /* input empty while scanning EOLs */
- goto out;
- switch (eol_count) {
- case 0:
- if (ss->EndOfLine) { /* EOL is required, but none is present. */
- status = ERRC;
- goto check;
- }
- case 1:
- break;
- default:
- status = ERRC;
- goto check;
- }
- }
- /* Now decode actual data. */
- if (k_left < 0) {
- if_debug0('w', "[w2]new row\n");
- status = cf_decode_2d(ss, pr);
- } else if (k_left == 0) {
- if_debug0('w', "[w1]new row\n");
- status = cf_decode_1d(ss, pr);
- } else {
- if_debug1('w', "[w1]new 2-D row, %d left\n", k_left);
- status = cf_decode_2d(ss, pr);
- }
- if_debug3('w', "[w]CFD status = %d, wpos = %d, cbit = %d\n",
- status, ss->wpos, ss->cbit);
- check:switch (status) {
- case 1: /* output full */
- goto top;
- case ERRC:
- /* Check for special handling of damaged rows. */
- if (ss->damaged_rows >= ss->DamagedRowsBeforeError ||
- !(ss->EndOfLine && ss->K >= 0)
- )
- break;
- /* Substitute undamaged data if appropriate. */
- /****** NOT IMPLEMENTED YET ******/
- {
- ss->wpos = wstop;
- ss->cbit = -ss->Columns & 7;
- ss->run_color = 0;
- }
- ss->skipping_damage = true;
- goto top;
- default:
- ss->damaged_rows = 0; /* finished a good row */
- }
- out:ss->k_left = k_left;
- ss->rows_left = rows_left;
- ss->eol_count = eol_count;
- return status;
- }
- /*
- * Decode a leading EOL, if any.
- * If an EOL is present, skip over it and return 1;
- * if no EOL is present, read no input and return -N, where N is the
- * number of initial bits that can be skipped in the search for an EOL;
- * if more input is needed, return 0.
- * Note that if we detected an EOL, we know that we can back up over it;
- * if we detected an N-bit non-EOL, we know that at least N bits of data
- * are available in the buffer.
- */
- private int
- cf_decode_eol(stream_CFD_state * ss, stream_cursor_read * pr)
- {
- hcd_declare_state;
- int zeros;
- int look_ahead;
- hcd_load_state();
- for (zeros = 0; zeros < run_eol_code_length - 1; zeros++) {
- ensure_bits(1, out);
- if (peek_bits(1))
- return -(zeros + 1);
- skip_bits(1);
- }
- /* We definitely have an EOL. Skip further zero bits. */
- look_ahead = (ss->K > 0 ? 2 : 1);
- for (;;) {
- ensure_bits(look_ahead, back);
- if (peek_bits(1))
- break;
- skip_bits(1);
- }
- skip_bits(1);
- hcd_store_state();
- return 1;
- back: /*
- * We ran out of data while skipping zeros.
- * We know we are at a byte boundary, and have just skipped
- * at least run_eol_code_length - 1 zeros. However,
- * bits_left may be 1 if look_ahead == 2.
- */
- bits &= (1 << bits_left) - 1;
- bits_left += run_eol_code_length - 1;
- hcd_store_state();
- out:return 0;
- }
- /* Decode a 1-D scan line. */
- private int
- cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr)
- {
- cfd_declare_state;
- byte black_byte = (ss->BlackIs1 ? 0xff : 0);
- int end_bit = -ss->Columns & 7;
- byte *stop = ss->lbuf - 1 + ss->raster;
- int run_color = ss->run_color;
- int status;
- int bcnt;
- cfd_load_state();
- if_debug1('w', "[w1]entry run_color = %d\n", ss->run_color);
- if (ss->run_color > 0)
- goto db;
- else
- goto dw;
- #define q_at_stop() (q >= stop && (qbit <= end_bit || q > stop))
- top:run_color = 0;
- if (q_at_stop())
- goto done;
- dw: /* Decode a white run. */
- get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
- bcnt, "[w1]white", dwl, out0);
- if (bcnt < 0) { /* exceptional situation */
- switch (bcnt) {
- case run_uncompressed: /* Uncompressed data. */
- cfd_store_state();
- bcnt = cf_decode_uncompressed(ss, pr);
- if (bcnt < 0)
- return bcnt;
- cfd_load_state();
- if (bcnt)
- goto db;
- else
- goto dw;
- /*case run_error: */
- /*case run_zeros: *//* Premature end-of-line. */
- default:
- status = ERRC;
- goto out;
- }
- }
- skip_data(bcnt, dwx);
- if (q_at_stop()) {
- run_color = 0; /* not inside a run */
- goto done;
- }
- run_color = 1;
- db: /* Decode a black run. */
- get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
- bcnt, "[w1]black", dbl, out1);
- if (bcnt < 0) { /* All exceptional codes are invalid here. */
- /****** WRONG, uncompressed IS ALLOWED ******/
- status = ERRC;
- goto out;
- }
- /* Invert bits designated by black run. */
- invert_data(bcnt, black_byte, goto dbx, idb);
- goto top;
- dwx: /* If we run out of data after a makeup code, */
- /* note that we are still processing a white run. */
- run_color = -1;
- goto dw;
- dbx: /* If we run out of data after a makeup code, */
- /* note that we are still processing a black run. */
- run_color = 2;
- goto db;
- done:if (q > stop || qbit < end_bit)
- status = ERRC;
- else
- status = 1;
- out:cfd_store_state();
- ss->run_color = run_color;
- if_debug1('w', "[w1]exit run_color = %d\n", run_color);
- return status;
- out0: /* We already set run_color to 0 or -1. */
- status = 0;
- goto out;
- out1: /* We already set run_color to 1 or 2. */
- status = 0;
- goto out;
- }
- /* Decode a 2-D scan line. */
- private int
- cf_decode_2d(stream_CFD_state * ss, stream_cursor_read * pr)
- {
- cfd_declare_state;
- byte invert_white = (ss->BlackIs1 ? 0 : 0xff);
- byte black_byte = ~invert_white;
- byte invert = ss->invert;
- int end_count = -ss->Columns & 7;
- uint raster = ss->raster;
- byte *q0 = ss->lbuf;
- byte *prev_q01 = ss->lprev + 1;
- byte *endptr = q0 - 1 + raster;
- int init_count = raster << 3;
- register int count;
- int rlen;
- int status;
- cfd_load_state();
- count = ((endptr - q) << 3) + qbit;
- endptr[1] = 0xa0; /* a byte with some 0s and some 1s, */
- /* to ensure run scan will stop */
- if_debug1('W', "[w2]raster=%d\n", raster);
- switch (ss->run_color) {
- case -2:
- ss->run_color = 0;
- goto hww;
- case -1:
- ss->run_color = 0;
- goto hbw;
- case 1:
- ss->run_color = 0;
- goto hwb;
- case 2:
- ss->run_color = 0;
- goto hbb;
- /*case 0: */
- }
- top:if (count <= end_count) {
- status = (count < end_count ? ERRC : 1);
- goto out;
- }
- /* If invert == invert_white, white and black have their */
- /* correct meanings; if invert == ~invert_white, */
- /* black and white are interchanged. */
- if_debug1('W', "[w2]%4d:\n", count);
- #ifdef DEBUG
- /* Check the invariant between q, qbit, and count. */
- {
- int pcount = (endptr - q) * 8 + qbit;
- if (pcount != count)
- dlprintf2("[w2]Error: count=%d pcount=%d\n",
- count, pcount);
- }
- #endif
- /*
- * We could just use get_run here, but we can do better. However,
- * we must be careful to handle the case where the very last codes
- * in the input stream are 1-bit "vertical 0" codes: we can't just
- * use ensure_bits(3, ...) and go to get more data if it fails.
- */
- ensure_bits(3, out3);
- #define vertical_0 (countof(cf2_run_vertical) / 2)
- switch (peek_bits(3)) {
- default /*4..7*/ : /* vertical(0) */
- v0: skip_bits(1);
- rlen = vertical_0;
- break;
- case 2: /* vertical(+1) */
- skip_bits(3);
- rlen = vertical_0 + 1;
- break;
- case 3: /* vertical(-1) */
- skip_bits(3);
- rlen = vertical_0 - 1;
- break;
- case 1: /* horizontal */
- skip_bits(3);
- if (invert == invert_white)
- goto hww;
- else
- goto hbb;
- case 0: /* everything else */
- get_run(cf_2d_decode, cfd_2d_initial_bits, cfd_2d_min_bits,
- rlen, "[w2]", d2l, out0);
- /* rlen may be run2_pass, run_uncompressed, or */
- /* 0..countof(cf2_run_vertical)-1. */
- if (rlen < 0)
- switch (rlen) {
- case run2_pass:
- break;
- case run_uncompressed:
- {
- int which;
- cfd_store_state();
- which = cf_decode_uncompressed(ss, pr);
- if (which < 0) {
- status = which;
- goto out;
- }
- cfd_load_state();
- /****** ADJUST count ******/
- invert = (which ? ~invert_white : invert_white);
- }
- goto top;
- default: /* run_error, run_zeros */
- status = ERRC;
- goto out;
- }
- }
- /* Interpreting the run requires scanning the */
- /* previous ('reference') line. */
- {
- int prev_count = count;
- byte prev_data;
- int dlen;
- static const byte count_bit[8] =
- {0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40};
- byte *prev_q = prev_q01 + (q - q0);
- int plen;
- if (!(count & 7))
- prev_q++; /* because of skip macros */
- prev_data = prev_q[-1] ^ invert;
- /* Find the b1 transition. */
- if ((prev_data & count_bit[prev_count & 7]) &&
- (prev_count < init_count || invert != invert_white)
- ) { /* Look for changing white first. */
- if_debug1('W', " data=0x%x", prev_data);
- skip_black_pixels(prev_data, prev_q,
- prev_count, invert, plen);
- if (prev_count < end_count) /* overshot */
- prev_count = end_count;
- if_debug1('W', " b1 other=%d", prev_count);
- }
- if (prev_count != end_count) {
- if_debug1('W', " data=0x%x", prev_data);
- skip_white_pixels(prev_data, prev_q,
- prev_count, invert, plen);
- if (prev_count < end_count) /* overshot */
- prev_count = end_count;
- if_debug1('W', " b1 same=%d", prev_count);
- }
- /* b1 = prev_count; */
- if (rlen == run2_pass) { /* Pass mode. Find b2. */
- if (prev_count != end_count) {
- if_debug1('W', " data=0x%x", prev_data);
- skip_black_pixels(prev_data, prev_q,
- prev_count, invert, plen);
- if (prev_count < end_count) /* overshot */
- prev_count = end_count;
- }
- /* b2 = prev_count; */
- if_debug2('W', " b2=%d, pass %d\n",
- prev_count, count - prev_count);
- } else { /* Vertical coding. */
- /* Remember that count counts *down*. */
- prev_count += rlen - vertical_0; /* a1 */
- if_debug2('W', " vertical %d -> %d\n",
- rlen - vertical_0, prev_count);
- }
- /* Now either invert or skip from count */
- /* to prev_count, and reset count. */
- if (invert == invert_white) { /* Skip data bits. */
- q = endptr - (prev_count >> 3);
- qbit = prev_count & 7;
- } else { /* Invert data bits. */
- dlen = count - prev_count;
- invert_data(dlen, black_byte, DO_NOTHING, idd);
- }
- count = prev_count;
- if (rlen >= 0) /* vertical mode */
- invert = ~invert; /* polarity changes */
- }
- goto top;
- out3:
- if (bits_left > 0 && peek_bits(1)) {
- /* This is a 1-bit "vertical 0" code, which we can still process. */
- goto v0;
- }
- /* falls through */
- out0:status = 0;
- /* falls through */
- out:cfd_store_state();
- ss->invert = invert;
- /* Ignore an error (missing EOFB/RTC when EndOfBlock == true) */
- /* if we have finished all rows. */
- if (status == ERRC && ss->Rows > 0 && ss->row > ss->Rows)
- status = EOFC;
- return status;
- /*
- * We handle horizontal decoding here, so that we can
- * branch back into it if we run out of input data.
- */
- /* White, then black. */
- hww:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
- rlen, " white", wwl, outww);
- if ((count -= rlen) < end_count) {
- status = ERRC;
- goto out;
- }
- skip_data(rlen, hww);
- /* Handle the second half of a white-black horizontal code. */
- hwb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
- rlen, " black", wbl, outwb);
- if ((count -= rlen) < end_count) {
- status = ERRC;
- goto out;
- }
- invert_data(rlen, black_byte, goto hwb, ihwb);
- goto top;
- outww:ss->run_color = -2;
- goto out0;
- outwb:ss->run_color = 1;
- goto out0;
- /* Black, then white. */
- hbb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
- rlen, " black", bbl, outbb);
- if ((count -= rlen) < end_count) {
- status = ERRC;
- goto out;
- }
- invert_data(rlen, black_byte, goto hbb, ihbb);
- /* Handle the second half of a black-white horizontal code. */
- hbw:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
- rlen, " white", bwl, outbw);
- if ((count -= rlen) < end_count) {
- status = ERRC;
- goto out;
- }
- skip_data(rlen, hbw);
- goto top;
- outbb:ss->run_color = 2;
- goto out0;
- outbw:ss->run_color = -1;
- goto out0;
- }
- #if 1 /*************** */
- private int
- cf_decode_uncompressed(stream_CFD_state * ss, stream_cursor_read * pr)
- {
- return ERRC;
- }
- #else /*************** */
- /* Decode uncompressed data. */
- /* (Not tested: no sample data available!) */
- /****** DOESN'T CHECK FOR OVERFLOWING SCAN LINE ******/
- private int
- cf_decode_uncompressed(stream * s)
- {
- cfd_declare_state;
- const cfd_node *np;
- int clen, rlen;
- cfd_load_state();
- while (1) {
- ensure_bits(cfd_uncompressed_initial_bits, NOOUT);
- np = &cf_uncompressed_decode[peek_bits(cfd_uncompressed_initial_bits)];
- clen = np->code_length;
- rlen = np->run_length;
- if (clen > cfd_uncompressed_initial_bits) { /* Must be an exit code. */
- break;
- }
- if (rlen == cfd_uncompressed_initial_bits) { /* Longest representable white run */
- if_debug1('W', "[wu]%d\n", rlen);
- if ((qbit -= cfd_uncompressed_initial_bits) < 0)
- qbit += 8, q++;
- } else {
- if_debug1('W', "[wu]%d+1\n", rlen);
- if (qbit -= rlen < 0)
- qbit += 8, q++;
- *q ^= 1 << qbit;
- }
- skip_bits(clen);
- }
- clen -= cfd_uncompressed_initial_bits;
- skip_bits(cfd_uncompressed_initial_bits);
- ensure_bits(clen, NOOUT);
- np = &cf_uncompressed_decode[rlen + peek_var_bits(clen)];
- rlen = np->run_length;
- skip_bits(np->code_length);
- if_debug1('w', "[wu]exit %d\n", rlen);
- if (rlen >= 0) { /* Valid exit code, rlen = 2 * run length + next polarity */
- if ((qbit -= rlen >> 1) < 0)
- qbit += 8, q++;
- rlen &= 1;
- }
- out:
- /******* WRONG ******/
- cfd_store_state();
- return rlen;
- }
- #endif /*************** */
- /* Stream template */
- const stream_template s_CFD_template =
- {&st_CFD_state, s_CFD_init, s_CFD_process, 1, 1, s_CFD_release,
- s_CFD_set_defaults
- };
|