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