Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4680 | right-hear | 1 | #include "fitz.h" |
2 | |||
3 | /* Fax G3/G4 decoder */ |
||
4 | |||
5 | /* TODO: uncompressed */ |
||
6 | |||
7 | /* |
||
8 |
|
||
9 |
|
||
10 |
|
||
11 |
|
||
12 |
|
||
13 |
|
||
14 | ... if (n_bits > initial_bits) ... |
||
15 |
|
||
16 |
|
||
17 |
|
||
18 |
|
||
19 | */ |
||
20 | |||
21 | typedef struct cfd_node_s cfd_node; |
||
22 | |||
23 | struct cfd_node_s |
||
24 | { |
||
25 | short val; |
||
26 | short nbits; |
||
27 | }; |
||
28 | |||
29 | enum |
||
30 | { |
||
31 | cfd_white_initial_bits = 8, |
||
32 | cfd_black_initial_bits = 7, |
||
33 | cfd_2d_initial_bits = 7, |
||
34 | cfd_uncompressed_initial_bits = 6 /* must be 6 */ |
||
35 | }; |
||
36 | |||
37 | /* non-run codes in tables */ |
||
38 | enum |
||
39 | { |
||
40 | ERROR = -1, |
||
41 | ZEROS = -2, /* EOL follows, possibly with more padding first */ |
||
42 | UNCOMPRESSED = -3 |
||
43 | }; |
||
44 | |||
45 | /* semantic codes for cf_2d_decode */ |
||
46 | enum |
||
47 | { |
||
48 | P = -4, |
||
49 | H = -5, |
||
50 | VR3 = 0, |
||
51 | VR2 = 1, |
||
52 | VR1 = 2, |
||
53 | V0 = 3, |
||
54 | VL1 = 4, |
||
55 | VL2 = 5, |
||
56 | VL3 = 6 |
||
57 | }; |
||
58 | |||
59 | /* White decoding table. */ |
||
60 | const cfd_node cf_white_decode[] = { |
||
61 | {256,12},{272,12},{29,8},{30,8},{45,8},{46,8},{22,7},{22,7}, |
||
62 | {23,7},{23,7},{47,8},{48,8},{13,6},{13,6},{13,6},{13,6},{20,7}, |
||
63 | {20,7},{33,8},{34,8},{35,8},{36,8},{37,8},{38,8},{19,7},{19,7}, |
||
64 | {31,8},{32,8},{1,6},{1,6},{1,6},{1,6},{12,6},{12,6},{12,6},{12,6}, |
||
65 | {53,8},{54,8},{26,7},{26,7},{39,8},{40,8},{41,8},{42,8},{43,8}, |
||
66 | {44,8},{21,7},{21,7},{28,7},{28,7},{61,8},{62,8},{63,8},{0,8}, |
||
67 | {320,8},{384,8},{10,5},{10,5},{10,5},{10,5},{10,5},{10,5},{10,5}, |
||
68 | {10,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5}, |
||
69 | {27,7},{27,7},{59,8},{60,8},{288,9},{290,9},{18,7},{18,7},{24,7}, |
||
70 | {24,7},{49,8},{50,8},{51,8},{52,8},{25,7},{25,7},{55,8},{56,8}, |
||
71 | {57,8},{58,8},{192,6},{192,6},{192,6},{192,6},{1664,6},{1664,6}, |
||
72 | {1664,6},{1664,6},{448,8},{512,8},{292,9},{640,8},{576,8},{294,9}, |
||
73 | {296,9},{298,9},{300,9},{302,9},{256,7},{256,7},{2,4},{2,4},{2,4}, |
||
74 | {2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4}, |
||
75 | {2,4},{2,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4}, |
||
76 | {3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{128,5},{128,5},{128,5}, |
||
77 | {128,5},{128,5},{128,5},{128,5},{128,5},{8,5},{8,5},{8,5},{8,5}, |
||
78 | {8,5},{8,5},{8,5},{8,5},{9,5},{9,5},{9,5},{9,5},{9,5},{9,5},{9,5}, |
||
79 | {9,5},{16,6},{16,6},{16,6},{16,6},{17,6},{17,6},{17,6},{17,6}, |
||
80 | {4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4}, |
||
81 | {4,4},{4,4},{4,4},{4,4},{4,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4}, |
||
82 | {5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4}, |
||
83 | {14,6},{14,6},{14,6},{14,6},{15,6},{15,6},{15,6},{15,6},{64,5}, |
||
84 | {64,5},{64,5},{64,5},{64,5},{64,5},{64,5},{64,5},{6,4},{6,4}, |
||
85 | {6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4}, |
||
86 | {6,4},{6,4},{6,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4}, |
||
87 | {7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{-2,3},{-2,3}, |
||
88 | {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
||
89 | {-1,0},{-1,0},{-1,0},{-1,0},{-3,4},{1792,3},{1792,3},{1984,4}, |
||
90 | {2048,4},{2112,4},{2176,4},{2240,4},{2304,4},{1856,3},{1856,3}, |
||
91 | {1920,3},{1920,3},{2368,4},{2432,4},{2496,4},{2560,4},{1472,1}, |
||
92 | {1536,1},{1600,1},{1728,1},{704,1},{768,1},{832,1},{896,1}, |
||
93 | {960,1},{1024,1},{1088,1},{1152,1},{1216,1},{1280,1},{1344,1}, |
||
94 | {1408,1} |
||
95 | }; |
||
96 | |||
97 | /* Black decoding table. */ |
||
98 | const cfd_node cf_black_decode[] = { |
||
99 | {128,12},{160,13},{224,12},{256,12},{10,7},{11,7},{288,12},{12,7}, |
||
100 | {9,6},{9,6},{8,6},{8,6},{7,5},{7,5},{7,5},{7,5},{6,4},{6,4},{6,4}, |
||
101 | {6,4},{6,4},{6,4},{6,4},{6,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4}, |
||
102 | {5,4},{5,4},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3}, |
||
103 | {1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{4,3},{4,3},{4,3},{4,3}, |
||
104 | {4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3}, |
||
105 | {4,3},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2}, |
||
106 | {3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2}, |
||
107 | {3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2}, |
||
108 | {2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2}, |
||
109 | {2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2}, |
||
110 | {2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2}, |
||
111 | {-2,4},{-2,4},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
||
112 | {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-3,5},{1792,4}, |
||
113 | {1792,4},{1984,5},{2048,5},{2112,5},{2176,5},{2240,5},{2304,5}, |
||
114 | {1856,4},{1856,4},{1920,4},{1920,4},{2368,5},{2432,5},{2496,5}, |
||
115 | {2560,5},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3}, |
||
116 | {52,5},{52,5},{640,6},{704,6},{768,6},{832,6},{55,5},{55,5}, |
||
117 | {56,5},{56,5},{1280,6},{1344,6},{1408,6},{1472,6},{59,5},{59,5}, |
||
118 | {60,5},{60,5},{1536,6},{1600,6},{24,4},{24,4},{24,4},{24,4}, |
||
119 | {25,4},{25,4},{25,4},{25,4},{1664,6},{1728,6},{320,5},{320,5}, |
||
120 | {384,5},{384,5},{448,5},{448,5},{512,6},{576,6},{53,5},{53,5}, |
||
121 | {54,5},{54,5},{896,6},{960,6},{1024,6},{1088,6},{1152,6},{1216,6}, |
||
122 | {64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{13,1}, |
||
123 | {13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1}, |
||
124 | {13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{23,4},{23,4},{50,5}, |
||
125 | {51,5},{44,5},{45,5},{46,5},{47,5},{57,5},{58,5},{61,5},{256,5}, |
||
126 | {16,3},{16,3},{16,3},{16,3},{17,3},{17,3},{17,3},{17,3},{48,5}, |
||
127 | {49,5},{62,5},{63,5},{30,5},{31,5},{32,5},{33,5},{40,5},{41,5}, |
||
128 | {22,4},{22,4},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1}, |
||
129 | {14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1}, |
||
130 | {15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{128,5}, |
||
131 | {192,5},{26,5},{27,5},{28,5},{29,5},{19,4},{19,4},{20,4},{20,4}, |
||
132 | {34,5},{35,5},{36,5},{37,5},{38,5},{39,5},{21,4},{21,4},{42,5}, |
||
133 | {43,5},{0,3},{0,3},{0,3},{0,3} |
||
134 | }; |
||
135 | |||
136 | /* 2-D decoding table. */ |
||
137 | const cfd_node cf_2d_decode[] = { |
||
138 | {128,11},{144,10},{6,7},{0,7},{5,6},{5,6},{1,6},{1,6},{-4,4}, |
||
139 | {-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-5,3},{-5,3}, |
||
140 | {-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3}, |
||
141 | {-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{4,3},{4,3},{4,3},{4,3},{4,3}, |
||
142 | {4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3}, |
||
143 | {2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3}, |
||
144 | {2,3},{2,3},{2,3},{2,3},{2,3},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
||
145 | {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
||
146 | {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
||
147 | {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
||
148 | {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
||
149 | {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
||
150 | {3,1},{3,1},{3,1},{-2,4},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
||
151 | {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
||
152 | {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-3,3} |
||
153 | }; |
||
154 | |||
155 | /* Uncompresssed decoding table. */ |
||
156 | const cfd_node cf_uncompressed_decode[] = { |
||
157 | {64,12},{5,6},{4,5},{4,5},{3,4},{3,4},{3,4},{3,4},{2,3},{2,3}, |
||
158 | {2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{1,2},{1,2},{1,2},{1,2},{1,2}, |
||
159 | {1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2}, |
||
160 | {0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}, |
||
161 | {0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}, |
||
162 | {0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}, |
||
163 | {-1,0},{-1,0},{8,6},{9,6},{6,5},{6,5},{7,5},{7,5},{4,4},{4,4}, |
||
164 | {4,4},{4,4},{5,4},{5,4},{5,4},{5,4},{2,3},{2,3},{2,3},{2,3},{2,3}, |
||
165 | {2,3},{2,3},{2,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3}, |
||
166 | {0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2}, |
||
167 | {0,2},{0,2},{0,2},{0,2},{0,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2}, |
||
168 | {1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2} |
||
169 | }; |
||
170 | |||
171 | /* bit magic */ |
||
172 | |||
173 | static inline int getbit(const unsigned char *buf, int x) |
||
174 | { |
||
175 | return ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1; |
||
176 | } |
||
177 | |||
178 | static int |
||
179 | find_changing(const unsigned char *line, int x, int w) |
||
180 | { |
||
181 | int a, b; |
||
182 | |||
183 | if (!line) |
||
184 | return w; |
||
185 | |||
186 | if (x == -1) |
||
187 | { |
||
188 | a = 0; |
||
189 | x = 0; |
||
190 | } |
||
191 | else |
||
192 | { |
||
193 | a = getbit(line, x); |
||
194 | x++; |
||
195 | } |
||
196 | |||
197 | while (x < w) |
||
198 | { |
||
199 | b = getbit(line, x); |
||
200 | if (a != b) |
||
201 | break; |
||
202 | x++; |
||
203 | } |
||
204 | |||
205 | return x; |
||
206 | } |
||
207 | |||
208 | static int |
||
209 | find_changing_color(const unsigned char *line, int x, int w, int color) |
||
210 | { |
||
211 | if (!line) |
||
212 | return w; |
||
213 | |||
214 | x = find_changing(line, x, w); |
||
215 | |||
216 | if (x < w && getbit(line, x) != color) |
||
217 | x = find_changing(line, x, w); |
||
218 | |||
219 | return x; |
||
220 | } |
||
221 | |||
222 | static const unsigned char lm[8] = { |
||
223 | 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 |
||
224 | }; |
||
225 | |||
226 | static const unsigned char rm[8] = { |
||
227 | 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE |
||
228 | }; |
||
229 | |||
230 | static inline void setbits(unsigned char *line, int x0, int x1) |
||
231 | { |
||
232 | int a0, a1, b0, b1, a; |
||
233 | |||
234 | a0 = x0 >> 3; |
||
235 | a1 = x1 >> 3; |
||
236 | |||
237 | b0 = x0 & 7; |
||
238 | b1 = x1 & 7; |
||
239 | |||
240 | if (a0 == a1) |
||
241 | { |
||
242 | if (b1) |
||
243 | line[a0] |= lm[b0] & rm[b1]; |
||
244 | } |
||
245 | else |
||
246 | { |
||
247 | line[a0] |= lm[b0]; |
||
248 | for (a = a0 + 1; a < a1; a++) |
||
249 | line[a] = 0xFF; |
||
250 | if (b1) |
||
251 | line[a1] |= rm[b1]; |
||
252 | } |
||
253 | } |
||
254 | |||
255 | typedef struct fz_faxd_s fz_faxd; |
||
256 | |||
257 | enum |
||
258 | { |
||
259 | STATE_NORMAL, /* neutral state, waiting for any code */ |
||
260 | STATE_MAKEUP, /* got a 1d makeup code, waiting for terminating code */ |
||
261 | STATE_EOL, /* at eol, needs output buffer space */ |
||
262 | STATE_H1, STATE_H2, /* in H part 1 and 2 (both makeup and terminating codes) */ |
||
263 | STATE_DONE /* all done */ |
||
264 | }; |
||
265 | |||
266 | struct fz_faxd_s |
||
267 | { |
||
268 | fz_stream *chain; |
||
269 | |||
270 | int k; |
||
271 | int end_of_line; |
||
272 | int encoded_byte_align; |
||
273 | int columns; |
||
274 | int rows; |
||
275 | int end_of_block; |
||
276 | int black_is_1; |
||
277 | |||
278 | int stride; |
||
279 | int ridx; |
||
280 | |||
281 | int bidx; |
||
282 | unsigned int word; |
||
283 | |||
284 | int stage; |
||
285 | |||
286 | int a, c, dim, eolc; |
||
287 | unsigned char *ref; |
||
288 | unsigned char *dst; |
||
289 | unsigned char *rp, *wp; |
||
290 | }; |
||
291 | |||
292 | static inline void eat_bits(fz_faxd *fax, int nbits) |
||
293 | { |
||
294 | fax->word <<= nbits; |
||
295 | fax->bidx += nbits; |
||
296 | } |
||
297 | |||
298 | static int |
||
299 | fill_bits(fz_faxd *fax) |
||
300 | { |
||
301 | while (fax->bidx >= 8) |
||
302 | { |
||
303 | int c = fz_read_byte(fax->chain); |
||
304 | if (c == EOF) |
||
305 | return EOF; |
||
306 | fax->bidx -= 8; |
||
307 | fax->word |= c << fax->bidx; |
||
308 | } |
||
309 | return 0; |
||
310 | } |
||
311 | |||
312 | static int |
||
313 | get_code(fz_faxd *fax, const cfd_node *table, int initialbits) |
||
314 | { |
||
315 | unsigned int word = fax->word; |
||
316 | int tidx = word >> (32 - initialbits); |
||
317 | int val = table[tidx].val; |
||
318 | int nbits = table[tidx].nbits; |
||
319 | |||
320 | if (nbits > initialbits) |
||
321 | { |
||
322 | int mask = (1 << (32 - initialbits)) - 1; |
||
323 | tidx = val + ((word & mask) >> (32 - nbits)); |
||
324 | val = table[tidx].val; |
||
325 | nbits = initialbits + table[tidx].nbits; |
||
326 | } |
||
327 | |||
328 | eat_bits(fax, nbits); |
||
329 | |||
330 | return val; |
||
331 | } |
||
332 | |||
333 | /* decode one 1d code */ |
||
334 | static fz_error |
||
335 | dec1d(fz_faxd *fax) |
||
336 | { |
||
337 | int code; |
||
338 | |||
339 | if (fax->a == -1) |
||
340 | fax->a = 0; |
||
341 | |||
342 | if (fax->c) |
||
343 | code = get_code(fax, cf_black_decode, cfd_black_initial_bits); |
||
344 | else |
||
345 | code = get_code(fax, cf_white_decode, cfd_white_initial_bits); |
||
346 | |||
347 | if (code == UNCOMPRESSED) |
||
348 | return fz_throw("uncompressed data in faxd"); |
||
349 | |||
350 | if (code < 0) |
||
351 | return fz_throw("negative code in 1d faxd"); |
||
352 | |||
353 | if (fax->a + code > fax->columns) |
||
354 | return fz_throw("overflow in 1d faxd"); |
||
355 | |||
356 | if (fax->c) |
||
357 | setbits(fax->dst, fax->a, fax->a + code); |
||
358 | |||
359 | fax->a += code; |
||
360 | |||
361 | if (code < 64) |
||
362 | { |
||
363 | fax->c = !fax->c; |
||
364 | fax->stage = STATE_NORMAL; |
||
365 | } |
||
366 | else |
||
367 | fax->stage = STATE_MAKEUP; |
||
368 | |||
369 | return fz_okay; |
||
370 | } |
||
371 | |||
372 | /* decode one 2d code */ |
||
373 | static fz_error |
||
374 | dec2d(fz_faxd *fax) |
||
375 | { |
||
376 | int code, b1, b2; |
||
377 | |||
378 | if (fax->stage == STATE_H1 || fax->stage == STATE_H2) |
||
379 | { |
||
380 | if (fax->a == -1) |
||
381 | fax->a = 0; |
||
382 | |||
383 | if (fax->c) |
||
384 | code = get_code(fax, cf_black_decode, cfd_black_initial_bits); |
||
385 | else |
||
386 | code = get_code(fax, cf_white_decode, cfd_white_initial_bits); |
||
387 | |||
388 | if (code == UNCOMPRESSED) |
||
389 | return fz_throw("uncompressed data in faxd"); |
||
390 | |||
391 | if (code < 0) |
||
392 | return fz_throw("negative code in 2d faxd"); |
||
393 | |||
394 | if (fax->a + code > fax->columns) |
||
395 | return fz_throw("overflow in 2d faxd"); |
||
396 | |||
397 | if (fax->c) |
||
398 | setbits(fax->dst, fax->a, fax->a + code); |
||
399 | |||
400 | fax->a += code; |
||
401 | |||
402 | if (code < 64) |
||
403 | { |
||
404 | fax->c = !fax->c; |
||
405 | if (fax->stage == STATE_H1) |
||
406 | fax->stage = STATE_H2; |
||
407 | else if (fax->stage == STATE_H2) |
||
408 | fax->stage = STATE_NORMAL; |
||
409 | } |
||
410 | |||
411 | return fz_okay; |
||
412 | } |
||
413 | |||
414 | code = get_code(fax, cf_2d_decode, cfd_2d_initial_bits); |
||
415 | |||
416 | switch (code) |
||
417 | { |
||
418 | case H: |
||
419 | fax->stage = STATE_H1; |
||
420 | break; |
||
421 | |||
422 | case P: |
||
423 | b1 = find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
424 | if (b1 >= fax->columns) |
||
425 | b2 = fax->columns; |
||
426 | else |
||
427 | b2 = find_changing(fax->ref, b1, fax->columns); |
||
428 | if (fax->c) setbits(fax->dst, fax->a, b2); |
||
429 | fax->a = b2; |
||
430 | break; |
||
431 | |||
432 | case V0: |
||
433 | b1 = find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
434 | if (fax->c) setbits(fax->dst, fax->a, b1); |
||
435 | fax->a = b1; |
||
436 | fax->c = !fax->c; |
||
437 | break; |
||
438 | |||
439 | case VR1: |
||
440 | b1 = 1 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
441 | if (b1 >= fax->columns) b1 = fax->columns; |
||
442 | if (fax->c) setbits(fax->dst, fax->a, b1); |
||
443 | fax->a = b1; |
||
444 | fax->c = !fax->c; |
||
445 | break; |
||
446 | |||
447 | case VR2: |
||
448 | b1 = 2 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
449 | if (b1 >= fax->columns) b1 = fax->columns; |
||
450 | if (fax->c) setbits(fax->dst, fax->a, b1); |
||
451 | fax->a = b1; |
||
452 | fax->c = !fax->c; |
||
453 | break; |
||
454 | |||
455 | case VR3: |
||
456 | b1 = 3 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
457 | if (b1 >= fax->columns) b1 = fax->columns; |
||
458 | if (fax->c) setbits(fax->dst, fax->a, b1); |
||
459 | fax->a = b1; |
||
460 | fax->c = !fax->c; |
||
461 | break; |
||
462 | |||
463 | case VL1: |
||
464 | b1 = -1 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
465 | if (b1 < 0) b1 = 0; |
||
466 | if (fax->c) setbits(fax->dst, fax->a, b1); |
||
467 | fax->a = b1; |
||
468 | fax->c = !fax->c; |
||
469 | break; |
||
470 | |||
471 | case VL2: |
||
472 | b1 = -2 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
473 | if (b1 < 0) b1 = 0; |
||
474 | if (fax->c) setbits(fax->dst, fax->a, b1); |
||
475 | fax->a = b1; |
||
476 | fax->c = !fax->c; |
||
477 | break; |
||
478 | |||
479 | case VL3: |
||
480 | b1 = -3 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
||
481 | if (b1 < 0) b1 = 0; |
||
482 | if (fax->c) setbits(fax->dst, fax->a, b1); |
||
483 | fax->a = b1; |
||
484 | fax->c = !fax->c; |
||
485 | break; |
||
486 | |||
487 | case UNCOMPRESSED: |
||
488 | return fz_throw("uncompressed data in faxd"); |
||
489 | |||
490 | case ERROR: |
||
491 | return fz_throw("invalid code in 2d faxd"); |
||
492 | |||
493 | default: |
||
494 | return fz_throw("invalid code in 2d faxd (%d)", code); |
||
495 | } |
||
496 | |||
497 | return 0; |
||
498 | } |
||
499 | |||
500 | static int |
||
501 | read_faxd(fz_stream *stm, unsigned char *buf, int len) |
||
502 | { |
||
503 | fz_faxd *fax = stm->state; |
||
504 | unsigned char *p = buf; |
||
505 | unsigned char *ep = buf + len; |
||
506 | unsigned char *tmp; |
||
507 | fz_error error; |
||
508 | |||
509 | if (fax->stage == STATE_DONE) |
||
510 | return 0; |
||
511 | |||
512 | if (fax->stage == STATE_EOL) |
||
513 | goto eol; |
||
514 | |||
515 | loop: |
||
516 | |||
517 | if (fill_bits(fax)) |
||
518 | { |
||
519 | if (fax->bidx > 31) |
||
520 | { |
||
521 | if (fax->a > 0) |
||
522 | goto eol; |
||
523 | goto rtc; |
||
524 | } |
||
525 | } |
||
526 | |||
527 | if ((fax->word >> (32 - 12)) == 0) |
||
528 | { |
||
529 | eat_bits(fax, 1); |
||
530 | goto loop; |
||
531 | } |
||
532 | |||
533 | if ((fax->word >> (32 - 12)) == 1) |
||
534 | { |
||
535 | eat_bits(fax, 12); |
||
536 | fax->eolc ++; |
||
537 | |||
538 | if (fax->k > 0) |
||
539 | { |
||
540 | if (fax->a == -1) |
||
541 | fax->a = 0; |
||
542 | if ((fax->word >> (32 - 1)) == 1) |
||
543 | fax->dim = 1; |
||
544 | else |
||
545 | fax->dim = 2; |
||
546 | eat_bits(fax, 1); |
||
547 | } |
||
548 | } |
||
549 | else if (fax->k > 0 && fax->a == -1) |
||
550 | { |
||
551 | fax->a = 0; |
||
552 | if ((fax->word >> (32 - 1)) == 1) |
||
553 | fax->dim = 1; |
||
554 | else |
||
555 | fax->dim = 2; |
||
556 | eat_bits(fax, 1); |
||
557 | } |
||
558 | else if (fax->dim == 1) |
||
559 | { |
||
560 | fax->eolc = 0; |
||
561 | error = dec1d(fax); |
||
562 | if (error) |
||
563 | return fz_rethrow(error, "cannot decode 1d code"); |
||
564 | } |
||
565 | else if (fax->dim == 2) |
||
566 | { |
||
567 | fax->eolc = 0; |
||
568 | error = dec2d(fax); |
||
569 | if (error) |
||
570 | return fz_rethrow(error, "cannot decode 2d code"); |
||
571 | } |
||
572 | |||
573 | /* no eol check after makeup codes nor in the middle of an H code */ |
||
574 | if (fax->stage == STATE_MAKEUP || fax->stage == STATE_H1 || fax->stage == STATE_H2) |
||
575 | goto loop; |
||
576 | |||
577 | /* check for eol conditions */ |
||
578 | if (fax->eolc || fax->a >= fax->columns) |
||
579 | { |
||
580 | if (fax->a > 0) |
||
581 | goto eol; |
||
582 | if (fax->eolc == (fax->k < 0 ? 2 : 6)) |
||
583 | goto rtc; |
||
584 | } |
||
585 | |||
586 | goto loop; |
||
587 | |||
588 | eol: |
||
589 | fax->stage = STATE_EOL; |
||
590 | |||
591 | if (fax->black_is_1) |
||
592 | { |
||
593 | while (fax->rp < fax->wp && p < ep) |
||
594 | *p++ = *fax->rp++; |
||
595 | } |
||
596 | else |
||
597 | { |
||
598 | while (fax->rp < fax->wp && p < ep) |
||
599 | *p++ = *fax->rp++ ^ 0xff; |
||
600 | } |
||
601 | |||
602 | if (fax->rp < fax->wp) |
||
603 | return p - buf; |
||
604 | |||
605 | tmp = fax->ref; |
||
606 | fax->ref = fax->dst; |
||
607 | fax->dst = tmp; |
||
608 | memset(fax->dst, 0, fax->stride); |
||
609 | |||
610 | fax->rp = fax->dst; |
||
611 | fax->wp = fax->dst + fax->stride; |
||
612 | |||
613 | fax->stage = STATE_NORMAL; |
||
614 | fax->c = 0; |
||
615 | fax->a = -1; |
||
616 | fax->ridx ++; |
||
617 | |||
618 | if (!fax->end_of_block && fax->rows) |
||
619 | { |
||
620 | if (fax->ridx >= fax->rows) |
||
621 | goto rtc; |
||
622 | } |
||
623 | |||
624 | /* we have not read dim from eol, make a guess */ |
||
625 | if (fax->k > 0 && !fax->eolc && fax->a == -1) |
||
626 | { |
||
627 | if (fax->ridx % fax->k == 0) |
||
628 | fax->dim = 1; |
||
629 | else |
||
630 | fax->dim = 2; |
||
631 | } |
||
632 | |||
633 | /* if end_of_line & encoded_byte_align, EOLs are *not* optional */ |
||
634 | if (fax->encoded_byte_align) |
||
635 | { |
||
636 | if (fax->end_of_line) |
||
637 | eat_bits(fax, (12 - fax->bidx) & 7); |
||
638 | else |
||
639 | eat_bits(fax, (8 - fax->bidx) & 7); |
||
640 | } |
||
641 | |||
642 | /* no more space in output, don't decode the next row yet */ |
||
643 | if (p == buf + len) |
||
644 | return p - buf; |
||
645 | |||
646 | goto loop; |
||
647 | |||
648 | rtc: |
||
649 | fax->stage = STATE_DONE; |
||
650 | return p - buf; |
||
651 | } |
||
652 | |||
653 | static void |
||
654 | close_faxd(fz_stream *stm) |
||
655 | { |
||
656 | fz_faxd *fax = stm->state; |
||
657 | int i; |
||
658 | |||
659 | /* if we read any extra bytes, try to put them back */ |
||
660 | i = (32 - fax->bidx) / 8; |
||
661 | while (i--) |
||
662 | fz_unread_byte(fax->chain); |
||
663 | |||
664 | fz_close(fax->chain); |
||
665 | fz_free(fax->ref); |
||
666 | fz_free(fax->dst); |
||
667 | fz_free(fax); |
||
668 | } |
||
669 | |||
670 | fz_stream * |
||
671 | fz_open_faxd(fz_stream *chain, fz_obj *params) |
||
672 | { |
||
673 | fz_faxd *fax; |
||
674 | fz_obj *obj; |
||
675 | |||
676 | fax = fz_malloc(sizeof(fz_faxd)); |
||
677 | fax->chain = chain; |
||
678 | |||
679 | fax->ref = NULL; |
||
680 | fax->dst = NULL; |
||
681 | |||
682 | fax->k = 0; |
||
683 | fax->end_of_line = 0; |
||
684 | fax->encoded_byte_align = 0; |
||
685 | fax->columns = 1728; |
||
686 | fax->rows = 0; |
||
687 | fax->end_of_block = 1; |
||
688 | fax->black_is_1 = 0; |
||
689 | |||
690 | obj = fz_dict_gets(params, "K"); |
||
691 | if (obj) fax->k = fz_to_int(obj); |
||
692 | |||
693 | obj = fz_dict_gets(params, "EndOfLine"); |
||
694 | if (obj) fax->end_of_line = fz_to_bool(obj); |
||
695 | |||
696 | obj = fz_dict_gets(params, "EncodedByteAlign"); |
||
697 | if (obj) fax->encoded_byte_align = fz_to_bool(obj); |
||
698 | |||
699 | obj = fz_dict_gets(params, "Columns"); |
||
700 | if (obj) fax->columns = fz_to_int(obj); |
||
701 | |||
702 | obj = fz_dict_gets(params, "Rows"); |
||
703 | if (obj) fax->rows = fz_to_int(obj); |
||
704 | |||
705 | obj = fz_dict_gets(params, "EndOfBlock"); |
||
706 | if (obj) fax->end_of_block = fz_to_bool(obj); |
||
707 | |||
708 | obj = fz_dict_gets(params, "BlackIs1"); |
||
709 | if (obj) fax->black_is_1 = fz_to_bool(obj); |
||
710 | |||
711 | fax->stride = ((fax->columns - 1) >> 3) + 1; |
||
712 | fax->ridx = 0; |
||
713 | fax->bidx = 32; |
||
714 | fax->word = 0; |
||
715 | |||
716 | fax->stage = STATE_NORMAL; |
||
717 | fax->a = -1; |
||
718 | fax->c = 0; |
||
719 | fax->dim = fax->k < 0 ? 2 : 1; |
||
720 | fax->eolc = 0; |
||
721 | |||
722 | fax->ref = fz_malloc(fax->stride); |
||
723 | fax->dst = fz_malloc(fax->stride); |
||
724 | fax->rp = fax->dst; |
||
725 | fax->wp = fax->dst + fax->stride; |
||
726 | |||
727 | memset(fax->ref, 0, fax->stride); |
||
728 | memset(fax->dst, 0, fax->stride); |
||
729 | |||
730 | return fz_new_stream(fax, read_faxd, close_faxd); |
||
731 | }>>>>>>>>>>>>>>><>><>=><=>>>> |