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