xref: /plan9/sys/src/cmd/gs/src/scfd.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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