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