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