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