Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
};