1 /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: scfd.c,v 1.9 2005/09/21 03:24:16 ray Exp $ */
18 /* CCITTFax decoding filter */
19 #include "stdio_.h" /* includes std.h */
20 #include "memory_.h"
21 #include "gdebug.h"
22 #include "strimpl.h"
23 #include "scf.h"
24 #include "scfx.h"
25
26 /* ------ CCITTFaxDecode ------ */
27
28 private_st_CFD_state();
29
30 /* Set default parameter values. */
31 private void
s_CFD_set_defaults(register stream_state * st)32 s_CFD_set_defaults(register stream_state * st)
33 {
34 stream_CFD_state *const ss = (stream_CFD_state *) st;
35
36 s_CFD_set_defaults_inline(ss);
37 }
38
39 /* Initialize CCITTFaxDecode filter */
40 private int
s_CFD_init(stream_state * st)41 s_CFD_init(stream_state * st)
42 {
43 stream_CFD_state *const ss = (stream_CFD_state *) st;
44 int raster = ss->raster =
45 ROUND_UP((ss->Columns + 7) >> 3, ss->DecodedByteAlign);
46 byte white = (ss->BlackIs1 ? 0 : 0xff);
47
48 s_hcd_init_inline(ss);
49 /* Because skip_white_pixels can look as many as 4 bytes ahead, */
50 /* we need to allow 4 extra bytes at the end of the row buffers. */
51 ss->lbuf = gs_alloc_bytes(st->memory, raster + 4, "CFD lbuf");
52 ss->lprev = 0;
53 if (ss->lbuf == 0)
54 return ERRC;
55 /****** WRONG ******/
56 if (ss->K != 0) {
57 ss->lprev = gs_alloc_bytes(st->memory, raster + 4, "CFD lprev");
58 if (ss->lprev == 0)
59 return ERRC;
60 /****** WRONG ******/
61 /* Clear the initial reference line for 2-D encoding. */
62 memset(ss->lbuf, white, raster);
63 /* Ensure that the scan of the reference line will stop. */
64 ss->lbuf[raster] = 0xa0;
65 }
66 ss->k_left = min(ss->K, 0);
67 ss->run_color = 0;
68 ss->damaged_rows = 0;
69 ss->skipping_damage = false;
70 ss->cbit = 0;
71 ss->uncomp_run = 0;
72 ss->rows_left = (ss->Rows <= 0 || ss->EndOfBlock ? -1 : ss->Rows + 1);
73 ss->row = 0;
74 ss->rpos = ss->wpos = raster - 1;
75 ss->eol_count = 0;
76 ss->invert = white;
77 ss->min_left = 1;
78 return 0;
79 }
80
81 /* Release the filter. */
82 private void
s_CFD_release(stream_state * st)83 s_CFD_release(stream_state * st)
84 {
85 stream_CFD_state *const ss = (stream_CFD_state *) st;
86
87 gs_free_object(st->memory, ss->lprev, "CFD lprev(close)");
88 gs_free_object(st->memory, ss->lbuf, "CFD lbuf(close)");
89 }
90
91 /* Declare the variables that hold the state. */
92 #define cfd_declare_state\
93 hcd_declare_state;\
94 register byte *q;\
95 int qbit
96 /* Load the state from the stream. */
97 #define cfd_load_state()\
98 hcd_load_state(),\
99 q = ss->lbuf + ss->wpos, qbit = ss->cbit
100 /* Store the state back in the stream. */
101 #define cfd_store_state()\
102 hcd_store_state(),\
103 ss->wpos = q - ss->lbuf, ss->cbit = qbit
104
105 /* Macros to get blocks of bits from the input stream. */
106 /* Invariants: 0 <= bits_left <= bits_size; */
107 /* bits [bits_left-1..0] contain valid data. */
108
109 #define avail_bits(n) hcd_bits_available(n)
110 #define ensure_bits(n, outl) hcd_ensure_bits(n, outl)
111 #define peek_bits(n) hcd_peek_bits(n)
112 #define peek_var_bits(n) hcd_peek_var_bits(n)
113 #define skip_bits(n) hcd_skip_bits(n)
114
115 /* Get a run from the stream. */
116 #ifdef DEBUG
117 # define IF_DEBUG(expr) expr
118 #else
119 # define IF_DEBUG(expr) DO_NOTHING
120 #endif
121 #define get_run(decode, initial_bits, min_bits, runlen, str, locl, outl)\
122 BEGIN\
123 const cfd_node *np;\
124 int clen;\
125 \
126 HCD_ENSURE_BITS_ELSE(initial_bits) {\
127 /* We might still have enough bits for the specific code. */\
128 if (bits_left < min_bits) goto outl;\
129 np = &decode[hcd_peek_bits_left() << (initial_bits - bits_left)];\
130 if ((clen = np->code_length) > bits_left) goto outl;\
131 goto locl;\
132 }\
133 np = &decode[peek_bits(initial_bits)];\
134 if ((clen = np->code_length) > initial_bits) {\
135 IF_DEBUG(uint init_bits = peek_bits(initial_bits));\
136 if (!avail_bits(clen)) goto outl;\
137 clen -= initial_bits;\
138 skip_bits(initial_bits);\
139 ensure_bits(clen, outl); /* can't goto outl */\
140 np = &decode[np->run_length + peek_var_bits(clen)];\
141 if_debug4('W', "%s xcode=0x%x,%d rlen=%d\n", str,\
142 (init_bits << np->code_length) +\
143 peek_var_bits(np->code_length),\
144 initial_bits + np->code_length,\
145 np->run_length);\
146 skip_bits(np->code_length);\
147 } else {\
148 locl: if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,\
149 peek_var_bits(clen), clen, np->run_length);\
150 skip_bits(clen);\
151 }\
152 runlen = np->run_length;\
153 END
154
155 /* Skip data bits for a white run. */
156 /* rlen is either less than 64, or a multiple of 64. */
157 #define skip_data(rlen, makeup_label)\
158 if ( (qbit -= rlen) < 0 )\
159 { q -= qbit >> 3, qbit &= 7;\
160 if ( rlen >= 64 ) goto makeup_label;\
161 }
162
163 /* Invert data bits for a black run. */
164 /* If rlen >= 64, execute makeup_action: this is to handle */
165 /* makeup codes efficiently, since these are always a multiple of 64. */
166 #define invert_data(rlen, black_byte, makeup_action, d)\
167 if ( rlen > qbit )\
168 { *q++ ^= (1 << qbit) - 1;\
169 rlen -= qbit;\
170 switch ( rlen >> 3 )\
171 {\
172 case 7: /* original rlen possibly >= 64 */\
173 if ( rlen + qbit >= 64 ) goto d;\
174 *q++ = black_byte;\
175 case 6: *q++ = black_byte;\
176 case 5: *q++ = black_byte;\
177 case 4: *q++ = black_byte;\
178 case 3: *q++ = black_byte;\
179 case 2: *q++ = black_byte;\
180 case 1: *q = black_byte;\
181 rlen &= 7;\
182 if ( !rlen ) { qbit = 0; break; }\
183 q++;\
184 case 0: /* know rlen != 0 */\
185 qbit = 8 - rlen;\
186 *q ^= 0xff << qbit;\
187 break;\
188 default: /* original rlen >= 64 */\
189 d: memset(q, black_byte, rlen >> 3);\
190 q += rlen >> 3;\
191 rlen &= 7;\
192 if ( !rlen ) qbit = 0, q--;\
193 else qbit = 8 - rlen, *q ^= 0xff << qbit;\
194 makeup_action;\
195 }\
196 }\
197 else\
198 qbit -= rlen,\
199 *q ^= ((1 << rlen) - 1) << qbit
200
201 /* Buffer refill for CCITTFaxDecode filter */
202 private int cf_decode_eol(stream_CFD_state *, stream_cursor_read *);
203 private int cf_decode_1d(stream_CFD_state *, stream_cursor_read *);
204 private int cf_decode_2d(stream_CFD_state *, stream_cursor_read *);
205 private int cf_decode_uncompressed(stream_CFD_state *, stream_cursor_read *);
206 private int
s_CFD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)207 s_CFD_process(stream_state * st, stream_cursor_read * pr,
208 stream_cursor_write * pw, bool last)
209 {
210 stream_CFD_state *const ss = (stream_CFD_state *) st;
211 int wstop = ss->raster - 1;
212 int eol_count = ss->eol_count;
213 int k_left = ss->k_left;
214 int rows_left = ss->rows_left;
215 int status = 0;
216
217 #ifdef DEBUG
218 const byte *rstart = pr->ptr;
219 const byte *wstart = pw->ptr;
220
221 #endif
222
223 top:
224 #ifdef DEBUG
225 {
226 hcd_declare_state;
227 hcd_load_state();
228 if_debug8('w', "[w]CFD_process top: eol_count=%d, k_left=%d, rows_left=%d\n"
229 " bits=0x%lx, bits_left=%d, read %u, wrote %u%s\n",
230 eol_count, k_left, rows_left,
231 (ulong) bits, bits_left,
232 (uint) (p - rstart), (uint) (pw->ptr - wstart),
233 (ss->skipping_damage ? ", skipping damage" : ""));
234 }
235 #endif
236 if (ss->skipping_damage) { /* Skip until we reach an EOL. */
237 hcd_declare_state;
238 int skip;
239
240 status = 0;
241 do {
242 switch ((skip = cf_decode_eol(ss, pr))) {
243 default: /* not EOL */
244 hcd_load_state();
245 skip_bits(-skip);
246 hcd_store_state();
247 continue;
248 case 0: /* need more input */
249 goto out;
250 case 1: /* EOL */
251 { /* Back up over the EOL. */
252 hcd_load_state();
253 bits_left += run_eol_code_length;
254 hcd_store_state();
255 }
256 ss->skipping_damage = false;
257 }
258 }
259 while (ss->skipping_damage);
260 ss->damaged_rows++;
261 }
262 /*
263 * Check for a completed input scan line. This isn't quite as
264 * simple as it seems, because we could have run out of input data
265 * between a makeup code and a 0-length termination code, or in a
266 * 2-D line before a final horizontal code with a 0-length second
267 * run. There's probably a way to think about this situation that
268 * doesn't require a special check, but I haven't found it yet.
269 */
270 if (ss->wpos == wstop && ss->cbit <= (-ss->Columns & 7) &&
271 (k_left == 0 ? !(ss->run_color & ~1) : ss->run_color == 0)
272 ) { /* Check for completed data to be copied to the client. */
273 /* (We could avoid the extra copy step for 1-D, but */
274 /* it's simpler not to, and it doesn't cost much.) */
275 if (ss->rpos < ss->wpos) {
276 stream_cursor_read cr;
277
278 cr.ptr = ss->lbuf + ss->rpos;
279 cr.limit = ss->lbuf + ss->wpos;
280 status = stream_move(&cr, pw);
281 ss->rpos = cr.ptr - ss->lbuf;
282 if (status)
283 goto out;
284 }
285 ss->row++;
286 if (rows_left > 0 && --rows_left == 0)
287 goto ck_eol; /* handle EOD if it is present */
288 if (ss->K != 0) {
289 byte *prev_bits = ss->lprev;
290
291 ss->lprev = ss->lbuf;
292 ss->lbuf = prev_bits;
293 if (ss->K > 0)
294 k_left = (k_left == 0 ? ss->K : k_left) - 1;
295 }
296 ss->rpos = ss->wpos = -1;
297 ss->eol_count = eol_count = 0;
298 ss->cbit = 0;
299 ss->invert = (ss->BlackIs1 ? 0 : 0xff);
300 memset(ss->lbuf, ss->invert, wstop + 1);
301 ss->run_color = 0;
302 /*
303 * If EndOfLine is true, we want to include the byte padding
304 * in the string of initial zeros in the EOL. If EndOfLine
305 * is false, we aren't sure what we should do....
306 */
307 if (ss->EncodedByteAlign & !ss->EndOfLine)
308 ss->bits_left &= ~7;
309 }
310 /* If we're between scan lines, scan for EOLs. */
311 if (ss->wpos < 0) {
312 /*
313 * According to Adobe, the decoder should always check for
314 * the EOD sequence, regardless of EndOfBlock: the Red Book's
315 * documentation of EndOfBlock is wrong.
316 */
317 ck_eol:
318 while ((status = cf_decode_eol(ss, pr)) > 0) {
319 if_debug0('w', "[w]EOL\n");
320 /* If we are in a Group 3 mixed regime, */
321 /* check the next bit for 1- vs. 2-D. */
322 if (ss->K > 0) {
323 hcd_declare_state;
324 hcd_load_state();
325 ensure_bits(1, out); /* can't fail */
326 k_left = (peek_bits(1) ? 0 : 1);
327 skip_bits(1);
328 hcd_store_state();
329 }
330 ++eol_count;
331 if (eol_count == (ss->K < 0 ? 2 : 6)) {
332 status = EOFC;
333 goto out;
334 }
335 }
336 if (rows_left == 0) {
337 status = EOFC;
338 goto out;
339 }
340 if (status == 0) /* input empty while scanning EOLs */
341 goto out;
342 switch (eol_count) {
343 case 0:
344 if (ss->EndOfLine) { /* EOL is required, but none is present. */
345 status = ERRC;
346 goto check;
347 }
348 case 1:
349 break;
350 default:
351 status = ERRC;
352 goto check;
353 }
354 }
355 /* Now decode actual data. */
356 if (k_left < 0) {
357 if_debug0('w', "[w2]new row\n");
358 status = cf_decode_2d(ss, pr);
359 } else if (k_left == 0) {
360 if_debug0('w', "[w1]new row\n");
361 status = cf_decode_1d(ss, pr);
362 } else {
363 if_debug1('w', "[w1]new 2-D row, %d left\n", k_left);
364 status = cf_decode_2d(ss, pr);
365 }
366 if_debug3('w', "[w]CFD status = %d, wpos = %d, cbit = %d\n",
367 status, ss->wpos, ss->cbit);
368 check:switch (status) {
369 case 1: /* output full */
370 goto top;
371 case ERRC:
372 /* Check for special handling of damaged rows. */
373 if (ss->damaged_rows >= ss->DamagedRowsBeforeError ||
374 !(ss->EndOfLine && ss->K >= 0)
375 )
376 break;
377 /* Substitute undamaged data if appropriate. */
378 /****** NOT IMPLEMENTED YET ******/
379 {
380 ss->wpos = wstop;
381 ss->cbit = -ss->Columns & 7;
382 ss->run_color = 0;
383 }
384 ss->skipping_damage = true;
385 goto top;
386 default:
387 ss->damaged_rows = 0; /* finished a good row */
388 }
389 out:ss->k_left = k_left;
390 ss->rows_left = rows_left;
391 ss->eol_count = eol_count;
392 return status;
393 }
394
395 /*
396 * Decode a leading EOL, if any.
397 * If an EOL is present, skip over it and return 1;
398 * if no EOL is present, read no input and return -N, where N is the
399 * number of initial bits that can be skipped in the search for an EOL;
400 * if more input is needed, return 0.
401 * Note that if we detected an EOL, we know that we can back up over it;
402 * if we detected an N-bit non-EOL, we know that at least N bits of data
403 * are available in the buffer.
404 */
405 private int
cf_decode_eol(stream_CFD_state * ss,stream_cursor_read * pr)406 cf_decode_eol(stream_CFD_state * ss, stream_cursor_read * pr)
407 {
408 hcd_declare_state;
409 int zeros;
410 int look_ahead;
411
412 hcd_load_state();
413 for (zeros = 0; zeros < run_eol_code_length - 1; zeros++) {
414 ensure_bits(1, out);
415 if (peek_bits(1))
416 return -(zeros + 1);
417 skip_bits(1);
418 }
419 /* We definitely have an EOL. Skip further zero bits. */
420 look_ahead = (ss->K > 0 ? 2 : 1);
421 for (;;) {
422 ensure_bits(look_ahead, back);
423 if (peek_bits(1))
424 break;
425 skip_bits(1);
426 }
427 skip_bits(1);
428 hcd_store_state();
429 return 1;
430 back: /*
431 * We ran out of data while skipping zeros.
432 * We know we are at a byte boundary, and have just skipped
433 * at least run_eol_code_length - 1 zeros. However,
434 * bits_left may be 1 if look_ahead == 2.
435 */
436 bits &= (1 << bits_left) - 1;
437 bits_left += run_eol_code_length - 1;
438 hcd_store_state();
439 out:return 0;
440 }
441
442 /* Decode a 1-D scan line. */
443 private int
cf_decode_1d(stream_CFD_state * ss,stream_cursor_read * pr)444 cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr)
445 {
446 cfd_declare_state;
447 byte black_byte = (ss->BlackIs1 ? 0xff : 0);
448 int end_bit = -ss->Columns & 7;
449 byte *stop = ss->lbuf - 1 + ss->raster;
450 int run_color = ss->run_color;
451 int status;
452 int bcnt;
453
454 cfd_load_state();
455 if_debug1('w', "[w1]entry run_color = %d\n", ss->run_color);
456 if (ss->run_color > 0)
457 goto db;
458 else
459 goto dw;
460 #define q_at_stop() (q >= stop && (qbit <= end_bit || q > stop))
461 top:run_color = 0;
462 if (q_at_stop())
463 goto done;
464 dw: /* Decode a white run. */
465 get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
466 bcnt, "[w1]white", dwl, out0);
467 if (bcnt < 0) { /* exceptional situation */
468 switch (bcnt) {
469 case run_uncompressed: /* Uncompressed data. */
470 cfd_store_state();
471 bcnt = cf_decode_uncompressed(ss, pr);
472 if (bcnt < 0)
473 return bcnt;
474 cfd_load_state();
475 if (bcnt)
476 goto db;
477 else
478 goto dw;
479 /*case run_error: */
480 /*case run_zeros: *//* Premature end-of-line. */
481 default:
482 status = ERRC;
483 goto out;
484 }
485 }
486 skip_data(bcnt, dwx);
487 if (q_at_stop()) {
488 run_color = 0; /* not inside a run */
489 goto done;
490 }
491 run_color = 1;
492 db: /* Decode a black run. */
493 get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
494 bcnt, "[w1]black", dbl, out1);
495 if (bcnt < 0) { /* All exceptional codes are invalid here. */
496 /****** WRONG, uncompressed IS ALLOWED ******/
497 status = ERRC;
498 goto out;
499 }
500 /* Invert bits designated by black run. */
501 invert_data(bcnt, black_byte, goto dbx, idb);
502 goto top;
503 dwx: /* If we run out of data after a makeup code, */
504 /* note that we are still processing a white run. */
505 run_color = -1;
506 goto dw;
507 dbx: /* If we run out of data after a makeup code, */
508 /* note that we are still processing a black run. */
509 run_color = 2;
510 goto db;
511 done:if (q > stop || qbit < end_bit)
512 status = ERRC;
513 else
514 status = 1;
515 out:cfd_store_state();
516 ss->run_color = run_color;
517 if_debug1('w', "[w1]exit run_color = %d\n", run_color);
518 return status;
519 out0: /* We already set run_color to 0 or -1. */
520 status = 0;
521 goto out;
522 out1: /* We already set run_color to 1 or 2. */
523 status = 0;
524 goto out;
525 }
526
527 /* Decode a 2-D scan line. */
528 private int
cf_decode_2d(stream_CFD_state * ss,stream_cursor_read * pr)529 cf_decode_2d(stream_CFD_state * ss, stream_cursor_read * pr)
530 {
531 cfd_declare_state;
532 byte invert_white = (ss->BlackIs1 ? 0 : 0xff);
533 byte black_byte = ~invert_white;
534 byte invert = ss->invert;
535 int end_count = -ss->Columns & 7;
536 uint raster = ss->raster;
537 byte *q0 = ss->lbuf;
538 byte *prev_q01 = ss->lprev + 1;
539 byte *endptr = q0 - 1 + raster;
540 int init_count = raster << 3;
541 register int count;
542 int rlen;
543 int status;
544
545 cfd_load_state();
546 count = ((endptr - q) << 3) + qbit;
547 endptr[1] = 0xa0; /* a byte with some 0s and some 1s, */
548 /* to ensure run scan will stop */
549 if_debug1('W', "[w2]raster=%d\n", raster);
550 switch (ss->run_color) {
551 case -2:
552 ss->run_color = 0;
553 goto hww;
554 case -1:
555 ss->run_color = 0;
556 goto hbw;
557 case 1:
558 ss->run_color = 0;
559 goto hwb;
560 case 2:
561 ss->run_color = 0;
562 goto hbb;
563 /*case 0: */
564 }
565 top:if (count <= end_count) {
566 status = (count < end_count ? ERRC : 1);
567 goto out;
568 }
569 /* If invert == invert_white, white and black have their */
570 /* correct meanings; if invert == ~invert_white, */
571 /* black and white are interchanged. */
572 if_debug1('W', "[w2]%4d:\n", count);
573 #ifdef DEBUG
574 /* Check the invariant between q, qbit, and count. */
575 {
576 int pcount = (endptr - q) * 8 + qbit;
577
578 if (pcount != count)
579 dlprintf2("[w2]Error: count=%d pcount=%d\n",
580 count, pcount);
581 }
582 #endif
583 /*
584 * We could just use get_run here, but we can do better. However,
585 * we must be careful to handle the case where the very last codes
586 * in the input stream are 1-bit "vertical 0" codes: we can't just
587 * use ensure_bits(3, ...) and go to get more data if it fails.
588 */
589 ensure_bits(3, out3);
590 #define vertical_0 (countof(cf2_run_vertical) / 2)
591 switch (peek_bits(3)) {
592 default /*4..7*/ : /* vertical(0) */
593 v0: skip_bits(1);
594 rlen = vertical_0;
595 break;
596 case 2: /* vertical(+1) */
597 skip_bits(3);
598 rlen = vertical_0 + 1;
599 break;
600 case 3: /* vertical(-1) */
601 skip_bits(3);
602 rlen = vertical_0 - 1;
603 break;
604 case 1: /* horizontal */
605 skip_bits(3);
606 if (invert == invert_white)
607 goto hww;
608 else
609 goto hbb;
610 case 0: /* everything else */
611 get_run(cf_2d_decode, cfd_2d_initial_bits, cfd_2d_min_bits,
612 rlen, "[w2]", d2l, out0);
613 /* rlen may be run2_pass, run_uncompressed, or */
614 /* 0..countof(cf2_run_vertical)-1. */
615 if (rlen < 0)
616 switch (rlen) {
617 case run2_pass:
618 break;
619 case run_uncompressed:
620 {
621 int which;
622
623 cfd_store_state();
624 which = cf_decode_uncompressed(ss, pr);
625 if (which < 0) {
626 status = which;
627 goto out;
628 }
629 cfd_load_state();
630 /****** ADJUST count ******/
631 invert = (which ? ~invert_white : invert_white);
632 }
633 goto top;
634 default: /* run_error, run_zeros */
635 status = ERRC;
636 goto out;
637 }
638 }
639 /* Interpreting the run requires scanning the */
640 /* previous ('reference') line. */
641 {
642 int prev_count = count;
643 byte prev_data;
644 int dlen;
645 static const byte count_bit[8] =
646 {0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40};
647 byte *prev_q = prev_q01 + (q - q0);
648 int plen;
649
650 if (!(count & 7))
651 prev_q++; /* because of skip macros */
652 prev_data = prev_q[-1] ^ invert;
653 /* Find the b1 transition. */
654 if ((prev_data & count_bit[prev_count & 7]) &&
655 (prev_count < init_count || invert != invert_white)
656 ) { /* Look for changing white first. */
657 if_debug1('W', " data=0x%x", prev_data);
658 skip_black_pixels(prev_data, prev_q,
659 prev_count, invert, plen);
660 if (prev_count < end_count) /* overshot */
661 prev_count = end_count;
662 if_debug1('W', " b1 other=%d", prev_count);
663 }
664 if (prev_count != end_count) {
665 if_debug1('W', " data=0x%x", prev_data);
666 skip_white_pixels(prev_data, prev_q,
667 prev_count, invert, plen);
668 if (prev_count < end_count) /* overshot */
669 prev_count = end_count;
670 if_debug1('W', " b1 same=%d", prev_count);
671 }
672 /* b1 = prev_count; */
673 if (rlen == run2_pass) { /* Pass mode. Find b2. */
674 if (prev_count != end_count) {
675 if_debug1('W', " data=0x%x", prev_data);
676 skip_black_pixels(prev_data, prev_q,
677 prev_count, invert, plen);
678 if (prev_count < end_count) /* overshot */
679 prev_count = end_count;
680 }
681 /* b2 = prev_count; */
682 if_debug2('W', " b2=%d, pass %d\n",
683 prev_count, count - prev_count);
684 } else { /* Vertical coding. */
685 /* Remember that count counts *down*. */
686 prev_count += rlen - vertical_0; /* a1 */
687 if_debug2('W', " vertical %d -> %d\n",
688 rlen - vertical_0, prev_count);
689 }
690 /* Now either invert or skip from count */
691 /* to prev_count, and reset count. */
692 if (invert == invert_white) { /* Skip data bits. */
693 q = endptr - (prev_count >> 3);
694 qbit = prev_count & 7;
695 } else { /* Invert data bits. */
696 dlen = count - prev_count;
697 invert_data(dlen, black_byte, DO_NOTHING, idd);
698 }
699 count = prev_count;
700 if (rlen >= 0) /* vertical mode */
701 invert = ~invert; /* polarity changes */
702 }
703 goto top;
704 out3:
705 if (bits_left > 0 && peek_bits(1)) {
706 /* This is a 1-bit "vertical 0" code, which we can still process. */
707 goto v0;
708 }
709 /* falls through */
710 out0:status = 0;
711 /* falls through */
712 out:cfd_store_state();
713 ss->invert = invert;
714 /* Ignore an error (missing EOFB/RTC when EndOfBlock == true) */
715 /* if we have finished all rows. */
716 if (status == ERRC && ss->Rows > 0 && ss->row > ss->Rows)
717 status = EOFC;
718 return status;
719 /*
720 * We handle horizontal decoding here, so that we can
721 * branch back into it if we run out of input data.
722 */
723 /* White, then black. */
724 hww:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
725 rlen, " white", wwl, outww);
726 if ((count -= rlen) < end_count) {
727 status = ERRC;
728 goto out;
729 }
730 skip_data(rlen, hww);
731 /* Handle the second half of a white-black horizontal code. */
732 hwb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
733 rlen, " black", wbl, outwb);
734 if ((count -= rlen) < end_count) {
735 status = ERRC;
736 goto out;
737 }
738 invert_data(rlen, black_byte, goto hwb, ihwb);
739 goto top;
740 outww:ss->run_color = -2;
741 goto out0;
742 outwb:ss->run_color = 1;
743 goto out0;
744 /* Black, then white. */
745 hbb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
746 rlen, " black", bbl, outbb);
747 if ((count -= rlen) < end_count) {
748 status = ERRC;
749 goto out;
750 }
751 invert_data(rlen, black_byte, goto hbb, ihbb);
752 /* Handle the second half of a black-white horizontal code. */
753 hbw:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
754 rlen, " white", bwl, outbw);
755 if ((count -= rlen) < end_count) {
756 status = ERRC;
757 goto out;
758 }
759 skip_data(rlen, hbw);
760 goto top;
761 outbb:ss->run_color = 2;
762 goto out0;
763 outbw:ss->run_color = -1;
764 goto out0;
765 }
766
767 #if 1 /*************** */
768 private int
cf_decode_uncompressed(stream_CFD_state * ss,stream_cursor_read * pr)769 cf_decode_uncompressed(stream_CFD_state * ss, stream_cursor_read * pr)
770 {
771 return ERRC;
772 }
773 #else /*************** */
774
775 /* Decode uncompressed data. */
776 /* (Not tested: no sample data available!) */
777 /****** DOESN'T CHECK FOR OVERFLOWING SCAN LINE ******/
778 private int
cf_decode_uncompressed(stream * s)779 cf_decode_uncompressed(stream * s)
780 {
781 cfd_declare_state;
782 const cfd_node *np;
783 int clen, rlen;
784
785 cfd_load_state();
786 while (1) {
787 ensure_bits(cfd_uncompressed_initial_bits, NOOUT);
788 np = &cf_uncompressed_decode[peek_bits(cfd_uncompressed_initial_bits)];
789 clen = np->code_length;
790 rlen = np->run_length;
791 if (clen > cfd_uncompressed_initial_bits) { /* Must be an exit code. */
792 break;
793 }
794 if (rlen == cfd_uncompressed_initial_bits) { /* Longest representable white run */
795 if_debug1('W', "[wu]%d\n", rlen);
796 if ((qbit -= cfd_uncompressed_initial_bits) < 0)
797 qbit += 8, q++;
798 } else {
799 if_debug1('W', "[wu]%d+1\n", rlen);
800 if (qbit -= rlen < 0)
801 qbit += 8, q++;
802 *q ^= 1 << qbit;
803 }
804 skip_bits(clen);
805 }
806 clen -= cfd_uncompressed_initial_bits;
807 skip_bits(cfd_uncompressed_initial_bits);
808 ensure_bits(clen, NOOUT);
809 np = &cf_uncompressed_decode[rlen + peek_var_bits(clen)];
810 rlen = np->run_length;
811 skip_bits(np->code_length);
812 if_debug1('w', "[wu]exit %d\n", rlen);
813 if (rlen >= 0) { /* Valid exit code, rlen = 2 * run length + next polarity */
814 if ((qbit -= rlen >> 1) < 0)
815 qbit += 8, q++;
816 rlen &= 1;
817 }
818 out:
819 /******* WRONG ******/
820 cfd_store_state();
821 return rlen;
822 }
823
824 #endif /*************** */
825
826 /* Stream template */
827 const stream_template s_CFD_template =
828 {&st_CFD_state, s_CFD_init, s_CFD_process, 1, 1, s_CFD_release,
829 s_CFD_set_defaults
830 };
831