Mercurial > hg > audiostuff
comparison spandsp-0.0.3/spandsp-0.0.3/src/t4.c @ 5:f762bf195c4b
import spandsp-0.0.3
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 16:00:21 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:26cd8f1ef0b1 | 5:f762bf195c4b |
---|---|
1 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * t4.c - ITU T.4 FAX image processing | |
5 * This depends on libtiff (see <http://www.libtiff.org>) | |
6 * | |
7 * Written by Steve Underwood <steveu@coppice.org> | |
8 * | |
9 * Copyright (C) 2003 Steve Underwood | |
10 * | |
11 * All rights reserved. | |
12 * | |
13 * This program is free software; you can redistribute it and/or modify | |
14 * it under the terms of the GNU General Public License version 2, as | |
15 * published by the Free Software Foundation. | |
16 * | |
17 * This program is distributed in the hope that it will be useful, | |
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 * GNU General Public License for more details. | |
21 * | |
22 * You should have received a copy of the GNU General Public License | |
23 * along with this program; if not, write to the Free Software | |
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
25 * | |
26 * $Id: t4.c,v 1.67 2006/12/01 18:00:48 steveu Exp $ | |
27 */ | |
28 | |
29 /* | |
30 * Much of this file is based on the T.4 and T.6 support in libtiff, which requires | |
31 * the following notice in any derived source code: | |
32 * | |
33 * Copyright (c) 1990-1997 Sam Leffler | |
34 * Copyright (c) 1991-1997 Silicon Graphics, Inc. | |
35 * | |
36 * Permission to use, copy, modify, distribute, and sell this software and | |
37 * its documentation for any purpose is hereby granted without fee, provided | |
38 * that (i) the above copyright notices and this permission notice appear in | |
39 * all copies of the software and related documentation, and (ii) the names of | |
40 * Sam Leffler and Silicon Graphics may not be used in any advertising or | |
41 * publicity relating to the software without the specific, prior written | |
42 * permission of Sam Leffler and Silicon Graphics. | |
43 * | |
44 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, | |
45 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY | |
46 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |
47 * | |
48 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR | |
49 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | |
50 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
51 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | |
52 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
53 * OF THIS SOFTWARE. | |
54 * | |
55 * Decoder support is derived from code in Frank Cringle's viewfax program; | |
56 * Copyright (C) 1990, 1995 Frank D. Cringle. | |
57 */ | |
58 | |
59 /*! \file */ | |
60 | |
61 #ifdef HAVE_CONFIG_H | |
62 #include <config.h> | |
63 #endif | |
64 | |
65 #define _GNU_SOURCE | |
66 | |
67 #include <stdio.h> | |
68 #include <inttypes.h> | |
69 #include <limits.h> | |
70 #include <unistd.h> | |
71 #include <fcntl.h> | |
72 #include <stdlib.h> | |
73 #include <time.h> | |
74 #include <memory.h> | |
75 #include <string.h> | |
76 #if defined(HAVE_TGMATH_H) | |
77 #include <tgmath.h> | |
78 #endif | |
79 #if defined(HAVE_MATH_H) | |
80 #include <math.h> | |
81 #endif | |
82 #include <tiffio.h> | |
83 | |
84 #include "spandsp/telephony.h" | |
85 #include "spandsp/logging.h" | |
86 #include "spandsp/bit_operations.h" | |
87 #include "spandsp/async.h" | |
88 #include "spandsp/t4.h" | |
89 | |
90 /* Finite state machine state codes */ | |
91 #define S_Null 0 | |
92 #define S_Pass 1 | |
93 #define S_Horiz 2 | |
94 #define S_V0 3 | |
95 #define S_VR 4 | |
96 #define S_VL 5 | |
97 #define S_Ext 6 | |
98 #define S_TermW 7 | |
99 #define S_TermB 8 | |
100 #define S_MakeUpW 9 | |
101 #define S_MakeUpB 10 | |
102 #define S_MakeUp 11 | |
103 #define S_EOL 12 | |
104 | |
105 #include "faxfont.h" | |
106 | |
107 #if 1 | |
108 #define STATE_TRACE(...) /**/ | |
109 #else | |
110 void STATE_TRACE(char *format, ...) | |
111 { | |
112 va_list arg_ptr; | |
113 | |
114 va_start(arg_ptr, format); | |
115 vprintf(format, arg_ptr); | |
116 va_end(arg_ptr); | |
117 } | |
118 /*- End of function --------------------------------------------------------*/ | |
119 #endif | |
120 | |
121 /* Finite state machine state table entry */ | |
122 typedef struct | |
123 { | |
124 uint8_t state; /* see above */ | |
125 uint8_t width; /* width of code in bits */ | |
126 uint32_t param; /* run length in bits */ | |
127 } T4_tab_entry; | |
128 | |
129 #include "t4states.h" | |
130 | |
131 /* From the T.4 spec: | |
132 | |
133 a0 The reference or starting changing element on the coding line. At | |
134 the start of the coding line, a0 is set on an imaginary white | |
135 changing element situated just before the first element on the | |
136 line. During the coding of the coding line, the position of a0 | |
137 is defined by the previous coding mode. (See 4.2.1.3.2.) | |
138 a1 The next changing element to the right of a0 on the coding line. | |
139 a2 The next changing element to the right of a1 on the coding line. | |
140 b1 The first changing element on the reference line to the right of | |
141 a0 and of opposite colour to a0. | |
142 b2 The next changing element to the right of b1 on the reference line. | |
143 */ | |
144 | |
145 /* | |
146 * ITU T.4 1D Huffman run length codes and | |
147 * related definitions. Given the small sizes | |
148 * of these tables it does not seem | |
149 * worthwhile to make code & length 8 bits. | |
150 */ | |
151 typedef struct | |
152 { | |
153 uint16_t length; /* length of T.4 code, in bits */ | |
154 uint16_t code; /* T.4 code */ | |
155 int16_t runlen; /* run length, in bits */ | |
156 } T4_table_entry; | |
157 | |
158 #define is_aligned(p,t) ((((intptr_t)(p)) & (sizeof(t) - 1)) == 0) | |
159 | |
160 /* Status values returned instead of a run length */ | |
161 #define T4CODE_EOL -1 /* NB: ACT_EOL - ACT_WRUNT */ | |
162 #define T4CODE_INVALID -2 /* NB: ACT_INVALID - ACT_WRUNT */ | |
163 #define T4CODE_EOF -3 /* end of input data */ | |
164 #define T4CODE_INCOMP -4 /* incomplete run code */ | |
165 | |
166 /* | |
167 * Note that these tables are ordered such that the | |
168 * index into the table is known to be either the | |
169 * run length, or (run length / 64) + a fixed offset. | |
170 * | |
171 * NB: The T4CODE_INVALID entries are only used | |
172 * during state generation (see mkg3states.c). | |
173 */ | |
174 const T4_table_entry t4_white_codes[] = | |
175 { | |
176 { 8, 0x35, 0 }, /* 0011 0101 */ | |
177 { 6, 0x07, 1 }, /* 0001 11 */ | |
178 { 4, 0x07, 2 }, /* 0111 */ | |
179 { 4, 0x08, 3 }, /* 1000 */ | |
180 { 4, 0x0B, 4 }, /* 1011 */ | |
181 { 4, 0x0C, 5 }, /* 1100 */ | |
182 { 4, 0x0E, 6 }, /* 1110 */ | |
183 { 4, 0x0F, 7 }, /* 1111 */ | |
184 { 5, 0x13, 8 }, /* 1001 1 */ | |
185 { 5, 0x14, 9 }, /* 1010 0 */ | |
186 { 5, 0x07, 10 }, /* 0011 1 */ | |
187 { 5, 0x08, 11 }, /* 0100 0 */ | |
188 { 6, 0x08, 12 }, /* 0010 00 */ | |
189 { 6, 0x03, 13 }, /* 0000 11 */ | |
190 { 6, 0x34, 14 }, /* 1101 00 */ | |
191 { 6, 0x35, 15 }, /* 1101 01 */ | |
192 { 6, 0x2A, 16 }, /* 1010 10 */ | |
193 { 6, 0x2B, 17 }, /* 1010 11 */ | |
194 { 7, 0x27, 18 }, /* 0100 111 */ | |
195 { 7, 0x0C, 19 }, /* 0001 100 */ | |
196 { 7, 0x08, 20 }, /* 0001 000 */ | |
197 { 7, 0x17, 21 }, /* 0010 111 */ | |
198 { 7, 0x03, 22 }, /* 0000 011 */ | |
199 { 7, 0x04, 23 }, /* 0000 100 */ | |
200 { 7, 0x28, 24 }, /* 0101 000 */ | |
201 { 7, 0x2B, 25 }, /* 0101 011 */ | |
202 { 7, 0x13, 26 }, /* 0010 011 */ | |
203 { 7, 0x24, 27 }, /* 0100 100 */ | |
204 { 7, 0x18, 28 }, /* 0011 000 */ | |
205 { 8, 0x02, 29 }, /* 0000 0010 */ | |
206 { 8, 0x03, 30 }, /* 0000 0011 */ | |
207 { 8, 0x1A, 31 }, /* 0001 1010 */ | |
208 { 8, 0x1B, 32 }, /* 0001 1011 */ | |
209 { 8, 0x12, 33 }, /* 0001 0010 */ | |
210 { 8, 0x13, 34 }, /* 0001 0011 */ | |
211 { 8, 0x14, 35 }, /* 0001 0100 */ | |
212 { 8, 0x15, 36 }, /* 0001 0101 */ | |
213 { 8, 0x16, 37 }, /* 0001 0110 */ | |
214 { 8, 0x17, 38 }, /* 0001 0111 */ | |
215 { 8, 0x28, 39 }, /* 0010 1000 */ | |
216 { 8, 0x29, 40 }, /* 0010 1001 */ | |
217 { 8, 0x2A, 41 }, /* 0010 1010 */ | |
218 { 8, 0x2B, 42 }, /* 0010 1011 */ | |
219 { 8, 0x2C, 43 }, /* 0010 1100 */ | |
220 { 8, 0x2D, 44 }, /* 0010 1101 */ | |
221 { 8, 0x04, 45 }, /* 0000 0100 */ | |
222 { 8, 0x05, 46 }, /* 0000 0101 */ | |
223 { 8, 0x0A, 47 }, /* 0000 1010 */ | |
224 { 8, 0x0B, 48 }, /* 0000 1011 */ | |
225 { 8, 0x52, 49 }, /* 0101 0010 */ | |
226 { 8, 0x53, 50 }, /* 0101 0011 */ | |
227 { 8, 0x54, 51 }, /* 0101 0100 */ | |
228 { 8, 0x55, 52 }, /* 0101 0101 */ | |
229 { 8, 0x24, 53 }, /* 0010 0100 */ | |
230 { 8, 0x25, 54 }, /* 0010 0101 */ | |
231 { 8, 0x58, 55 }, /* 0101 1000 */ | |
232 { 8, 0x59, 56 }, /* 0101 1001 */ | |
233 { 8, 0x5A, 57 }, /* 0101 1010 */ | |
234 { 8, 0x5B, 58 }, /* 0101 1011 */ | |
235 { 8, 0x4A, 59 }, /* 0100 1010 */ | |
236 { 8, 0x4B, 60 }, /* 0100 1011 */ | |
237 { 8, 0x32, 61 }, /* 0011 0010 */ | |
238 { 8, 0x33, 62 }, /* 0011 0011 */ | |
239 { 8, 0x34, 63 }, /* 0011 0100 */ | |
240 { 5, 0x1B, 64 }, /* 1101 1 */ | |
241 { 5, 0x12, 128 }, /* 1001 0 */ | |
242 { 6, 0x17, 192 }, /* 0101 11 */ | |
243 { 7, 0x37, 256 }, /* 0110 111 */ | |
244 { 8, 0x36, 320 }, /* 0011 0110 */ | |
245 { 8, 0x37, 384 }, /* 0011 0111 */ | |
246 { 8, 0x64, 448 }, /* 0110 0100 */ | |
247 { 8, 0x65, 512 }, /* 0110 0101 */ | |
248 { 8, 0x68, 576 }, /* 0110 1000 */ | |
249 { 8, 0x67, 640 }, /* 0110 0111 */ | |
250 { 9, 0xCC, 704 }, /* 0110 0110 0 */ | |
251 { 9, 0xCD, 768 }, /* 0110 0110 1 */ | |
252 { 9, 0xD2, 832 }, /* 0110 1001 0 */ | |
253 { 9, 0xD3, 896 }, /* 0110 1001 1 */ | |
254 { 9, 0xD4, 960 }, /* 0110 1010 0 */ | |
255 { 9, 0xD5, 1024 }, /* 0110 1010 1 */ | |
256 { 9, 0xD6, 1088 }, /* 0110 1011 0 */ | |
257 { 9, 0xD7, 1152 }, /* 0110 1011 1 */ | |
258 { 9, 0xD8, 1216 }, /* 0110 1100 0 */ | |
259 { 9, 0xD9, 1280 }, /* 0110 1100 1 */ | |
260 { 9, 0xDA, 1344 }, /* 0110 1101 0 */ | |
261 { 9, 0xDB, 1408 }, /* 0110 1101 1 */ | |
262 { 9, 0x98, 1472 }, /* 0100 1100 0 */ | |
263 { 9, 0x99, 1536 }, /* 0100 1100 1 */ | |
264 { 9, 0x9A, 1600 }, /* 0100 1101 0 */ | |
265 { 6, 0x18, 1664 }, /* 0110 00 */ | |
266 { 9, 0x9B, 1728 }, /* 0100 1101 1 */ | |
267 { 11, 0x08, 1792 }, /* 0000 0001 000 */ | |
268 { 11, 0x0C, 1856 }, /* 0000 0001 100 */ | |
269 { 11, 0x0D, 1920 }, /* 0000 0001 101 */ | |
270 { 12, 0x12, 1984 }, /* 0000 0001 0010 */ | |
271 { 12, 0x13, 2048 }, /* 0000 0001 0011 */ | |
272 { 12, 0x14, 2112 }, /* 0000 0001 0100 */ | |
273 { 12, 0x15, 2176 }, /* 0000 0001 0101 */ | |
274 { 12, 0x16, 2240 }, /* 0000 0001 0110 */ | |
275 { 12, 0x17, 2304 }, /* 0000 0001 0111 */ | |
276 { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ | |
277 { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ | |
278 { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ | |
279 { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ | |
280 { 12, 0x01, T4CODE_EOL }, /* 0000 0000 0001 */ | |
281 { 9, 0x01, T4CODE_INVALID }, /* 0000 0000 1 */ | |
282 { 10, 0x01, T4CODE_INVALID }, /* 0000 0000 01 */ | |
283 { 11, 0x01, T4CODE_INVALID }, /* 0000 0000 001 */ | |
284 { 12, 0x00, T4CODE_INVALID }, /* 0000 0000 0000 */ | |
285 }; | |
286 | |
287 const T4_table_entry t4_black_codes[] = | |
288 { | |
289 { 10, 0x37, 0 }, /* 0000 1101 11 */ | |
290 { 3, 0x02, 1 }, /* 010 */ | |
291 { 2, 0x03, 2 }, /* 11 */ | |
292 { 2, 0x02, 3 }, /* 10 */ | |
293 { 3, 0x03, 4 }, /* 011 */ | |
294 { 4, 0x03, 5 }, /* 0011 */ | |
295 { 4, 0x02, 6 }, /* 0010 */ | |
296 { 5, 0x03, 7 }, /* 0001 1 */ | |
297 { 6, 0x05, 8 }, /* 0001 01 */ | |
298 { 6, 0x04, 9 }, /* 0001 00 */ | |
299 { 7, 0x04, 10 }, /* 0000 100 */ | |
300 { 7, 0x05, 11 }, /* 0000 101 */ | |
301 { 7, 0x07, 12 }, /* 0000 111 */ | |
302 { 8, 0x04, 13 }, /* 0000 0100 */ | |
303 { 8, 0x07, 14 }, /* 0000 0111 */ | |
304 { 9, 0x18, 15 }, /* 0000 1100 0 */ | |
305 { 10, 0x17, 16 }, /* 0000 0101 11 */ | |
306 { 10, 0x18, 17 }, /* 0000 0110 00 */ | |
307 { 10, 0x08, 18 }, /* 0000 0010 00 */ | |
308 { 11, 0x67, 19 }, /* 0000 1100 111 */ | |
309 { 11, 0x68, 20 }, /* 0000 1101 000 */ | |
310 { 11, 0x6C, 21 }, /* 0000 1101 100 */ | |
311 { 11, 0x37, 22 }, /* 0000 0110 111 */ | |
312 { 11, 0x28, 23 }, /* 0000 0101 000 */ | |
313 { 11, 0x17, 24 }, /* 0000 0010 111 */ | |
314 { 11, 0x18, 25 }, /* 0000 0011 000 */ | |
315 { 12, 0xCA, 26 }, /* 0000 1100 1010 */ | |
316 { 12, 0xCB, 27 }, /* 0000 1100 1011 */ | |
317 { 12, 0xCC, 28 }, /* 0000 1100 1100 */ | |
318 { 12, 0xCD, 29 }, /* 0000 1100 1101 */ | |
319 { 12, 0x68, 30 }, /* 0000 0110 1000 */ | |
320 { 12, 0x69, 31 }, /* 0000 0110 1001 */ | |
321 { 12, 0x6A, 32 }, /* 0000 0110 1010 */ | |
322 { 12, 0x6B, 33 }, /* 0000 0110 1011 */ | |
323 { 12, 0xD2, 34 }, /* 0000 1101 0010 */ | |
324 { 12, 0xD3, 35 }, /* 0000 1101 0011 */ | |
325 { 12, 0xD4, 36 }, /* 0000 1101 0100 */ | |
326 { 12, 0xD5, 37 }, /* 0000 1101 0101 */ | |
327 { 12, 0xD6, 38 }, /* 0000 1101 0110 */ | |
328 { 12, 0xD7, 39 }, /* 0000 1101 0111 */ | |
329 { 12, 0x6C, 40 }, /* 0000 0110 1100 */ | |
330 { 12, 0x6D, 41 }, /* 0000 0110 1101 */ | |
331 { 12, 0xDA, 42 }, /* 0000 1101 1010 */ | |
332 { 12, 0xDB, 43 }, /* 0000 1101 1011 */ | |
333 { 12, 0x54, 44 }, /* 0000 0101 0100 */ | |
334 { 12, 0x55, 45 }, /* 0000 0101 0101 */ | |
335 { 12, 0x56, 46 }, /* 0000 0101 0110 */ | |
336 { 12, 0x57, 47 }, /* 0000 0101 0111 */ | |
337 { 12, 0x64, 48 }, /* 0000 0110 0100 */ | |
338 { 12, 0x65, 49 }, /* 0000 0110 0101 */ | |
339 { 12, 0x52, 50 }, /* 0000 0101 0010 */ | |
340 { 12, 0x53, 51 }, /* 0000 0101 0011 */ | |
341 { 12, 0x24, 52 }, /* 0000 0010 0100 */ | |
342 { 12, 0x37, 53 }, /* 0000 0011 0111 */ | |
343 { 12, 0x38, 54 }, /* 0000 0011 1000 */ | |
344 { 12, 0x27, 55 }, /* 0000 0010 0111 */ | |
345 { 12, 0x28, 56 }, /* 0000 0010 1000 */ | |
346 { 12, 0x58, 57 }, /* 0000 0101 1000 */ | |
347 { 12, 0x59, 58 }, /* 0000 0101 1001 */ | |
348 { 12, 0x2B, 59 }, /* 0000 0010 1011 */ | |
349 { 12, 0x2C, 60 }, /* 0000 0010 1100 */ | |
350 { 12, 0x5A, 61 }, /* 0000 0101 1010 */ | |
351 { 12, 0x66, 62 }, /* 0000 0110 0110 */ | |
352 { 12, 0x67, 63 }, /* 0000 0110 0111 */ | |
353 { 10, 0x0F, 64 }, /* 0000 0011 11 */ | |
354 { 12, 0xC8, 128 }, /* 0000 1100 1000 */ | |
355 { 12, 0xC9, 192 }, /* 0000 1100 1001 */ | |
356 { 12, 0x5B, 256 }, /* 0000 0101 1011 */ | |
357 { 12, 0x33, 320 }, /* 0000 0011 0011 */ | |
358 { 12, 0x34, 384 }, /* 0000 0011 0100 */ | |
359 { 12, 0x35, 448 }, /* 0000 0011 0101 */ | |
360 { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */ | |
361 { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */ | |
362 { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */ | |
363 { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */ | |
364 { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */ | |
365 { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */ | |
366 { 13, 0x72, 896 }, /* 0000 0011 1001 0 */ | |
367 { 13, 0x73, 960 }, /* 0000 0011 1001 1 */ | |
368 { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */ | |
369 { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */ | |
370 { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */ | |
371 { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */ | |
372 { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */ | |
373 { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */ | |
374 { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */ | |
375 { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */ | |
376 { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */ | |
377 { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */ | |
378 { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */ | |
379 { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */ | |
380 { 11, 0x08, 1792 }, /* 0000 0001 000 */ | |
381 { 11, 0x0C, 1856 }, /* 0000 0001 100 */ | |
382 { 11, 0x0D, 1920 }, /* 0000 0001 101 */ | |
383 { 12, 0x12, 1984 }, /* 0000 0001 0010 */ | |
384 { 12, 0x13, 2048 }, /* 0000 0001 0011 */ | |
385 { 12, 0x14, 2112 }, /* 0000 0001 0100 */ | |
386 { 12, 0x15, 2176 }, /* 0000 0001 0101 */ | |
387 { 12, 0x16, 2240 }, /* 0000 0001 0110 */ | |
388 { 12, 0x17, 2304 }, /* 0000 0001 0111 */ | |
389 { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ | |
390 { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ | |
391 { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ | |
392 { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ | |
393 { 12, 0x01, T4CODE_EOL }, /* 0000 0000 0001 */ | |
394 { 9, 0x01, T4CODE_INVALID }, /* 0000 0000 1 */ | |
395 { 10, 0x01, T4CODE_INVALID }, /* 0000 0000 01 */ | |
396 { 11, 0x01, T4CODE_INVALID }, /* 0000 0000 001 */ | |
397 { 12, 0x00, T4CODE_INVALID }, /* 0000 0000 0000 */ | |
398 }; | |
399 | |
400 #if defined(__i386__) || defined(__x86_64__) | |
401 static __inline__ int run_length(unsigned int bits) | |
402 { | |
403 return 7 - top_bit(bits); | |
404 } | |
405 /*- End of function --------------------------------------------------------*/ | |
406 #else | |
407 static __inline__ int run_length(unsigned int bits) | |
408 { | |
409 static const uint8_t run_len[256] = | |
410 { | |
411 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */ | |
412 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */ | |
413 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */ | |
414 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */ | |
415 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */ | |
416 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */ | |
417 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */ | |
418 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */ | |
419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ | |
420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ | |
421 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ | |
422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ | |
423 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ | |
424 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ | |
425 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ | |
426 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */ | |
427 }; | |
428 | |
429 return run_len[bits]; | |
430 } | |
431 /*- End of function --------------------------------------------------------*/ | |
432 #endif | |
433 | |
434 static __inline__ int flush_bits_to_image_buffer(t4_state_t *s) | |
435 { | |
436 uint8_t *t; | |
437 | |
438 s->bit = 8; | |
439 if (s->image_size >= s->image_buffer_size) | |
440 { | |
441 if ((t = realloc(s->image_buffer, s->image_buffer_size + 10000)) == NULL) | |
442 return -1; | |
443 s->image_buffer_size += 10000; | |
444 s->image_buffer = t; | |
445 } | |
446 s->image_buffer[s->image_size++] = (uint8_t) s->data; | |
447 s->data = 0; | |
448 return 0; | |
449 } | |
450 /*- End of function --------------------------------------------------------*/ | |
451 | |
452 static __inline__ void put_run(t4_state_t *s, int black) | |
453 { | |
454 int i; | |
455 | |
456 s->row_len += s->run_length; | |
457 /* Ignore anything before the first EOL */ | |
458 /* Don't allow rows to grow too long, and overflow the buffers */ | |
459 if (s->row_len <= s->image_width) | |
460 { | |
461 *s->pa++ = s->run_length; | |
462 for (i = 0; i < s->run_length; i++) | |
463 { | |
464 s->data = (s->data << 1) | black; | |
465 if (--s->bit == 0) | |
466 flush_bits_to_image_buffer(s); | |
467 } | |
468 } | |
469 s->run_length = 0; | |
470 } | |
471 /*- End of function --------------------------------------------------------*/ | |
472 | |
473 static __inline__ void put_eol(t4_state_t *s) | |
474 { | |
475 uint32_t *x; | |
476 uint8_t *t; | |
477 | |
478 if (s->run_length) | |
479 put_run(s, 0); | |
480 if (s->row_len != s->image_width) | |
481 { | |
482 STATE_TRACE("%d Bad row - %d %d\n", s->row, s->row_len, s->row_is_2d); | |
483 /* Clean up the bad runs */ | |
484 while (s->a0 > s->image_width && s->pa > s->cur_runs) | |
485 s->a0 -= *--s->pa; | |
486 if (s->a0 < s->image_width) | |
487 { | |
488 if (s->a0 < 0) | |
489 s->a0 = 0; | |
490 if ((s->pa - s->cur_runs) & 1) | |
491 put_run(s, 0); | |
492 s->run_length = s->image_width - s->a0; | |
493 put_run(s, 0); | |
494 } | |
495 else if (s->a0 > s->image_width) | |
496 { | |
497 s->run_length = s->image_width; | |
498 put_run(s, 0); | |
499 s->run_length = 0; | |
500 put_run(s, 0); | |
501 } | |
502 if (s->row_starts_at != s->last_row_starts_at) | |
503 { | |
504 /* Copy the previous row over this one */ | |
505 if (s->row_starts_at + s->bytes_per_row >= s->image_buffer_size) | |
506 { | |
507 if ((t = realloc(s->image_buffer, s->image_buffer_size + 10000)) == NULL) | |
508 { | |
509 /* TODO: take some action to report the allocation failure */ | |
510 return; | |
511 } | |
512 s->image_buffer_size += 10000; | |
513 s->image_buffer = t; | |
514 } | |
515 memcpy(s->image_buffer + s->row_starts_at, s->image_buffer + s->last_row_starts_at, s->bytes_per_row); | |
516 s->image_size = s->row_starts_at + s->bytes_per_row; | |
517 } | |
518 s->bad_rows++; | |
519 s->curr_bad_row_run++; | |
520 } | |
521 else | |
522 { | |
523 if (s->curr_bad_row_run) | |
524 { | |
525 if (s->curr_bad_row_run > s->longest_bad_row_run) | |
526 s->longest_bad_row_run = s->curr_bad_row_run; | |
527 s->curr_bad_row_run = 0; | |
528 } | |
529 STATE_TRACE("%d Good row - %d %d\n", s->row, s->row_len, s->row_is_2d); | |
530 } | |
531 | |
532 #if 0 | |
533 /* Dump the runs of black and white for analysis */ | |
534 { | |
535 int total; | |
536 | |
537 span_log(&s->logging, SPAN_LOG_DEBUG_2, "Ref "); | |
538 total = 0; | |
539 for (x = s->ref_runs; x < s->pb; x++) | |
540 { | |
541 total += *x; | |
542 span_log(&s->logging, SPAN_LOG_DEBUG_2, "%d ", *x); | |
543 } | |
544 span_log(&s->logging, SPAN_LOG_DEBUG_2, " total = %d\n", total); | |
545 span_log(&s->logging, SPAN_LOG_DEBUG_2, "Cur "); | |
546 total = 0; | |
547 for (x = s->cur_runs; x < s->pa; x++) | |
548 { | |
549 total += *x; | |
550 span_log(&s->logging, SPAN_LOG_DEBUG_2, "%d ", *x); | |
551 } | |
552 span_log(&s->logging, SPAN_LOG_DEBUG_2, "total = %d\n", total); | |
553 } | |
554 #endif | |
555 | |
556 /* Prepare the buffers for the next row. */ | |
557 s->image_length++; | |
558 s->last_row_starts_at = s->row_starts_at; | |
559 s->row_starts_at = s->image_size; | |
560 x = s->cur_runs; | |
561 s->cur_runs = s->ref_runs; | |
562 s->ref_runs = x; | |
563 | |
564 s->pa = s->cur_runs; | |
565 s->pb = s->ref_runs; | |
566 | |
567 s->a0 = 0; | |
568 s->b1 = *s->pb++; | |
569 } | |
570 /*- End of function --------------------------------------------------------*/ | |
571 | |
572 int t4_rx_end_page(t4_state_t *s) | |
573 { | |
574 int row; | |
575 int i; | |
576 time_t now; | |
577 struct tm *tm; | |
578 char buf[256 + 1]; | |
579 uint16_t resunit; | |
580 float x_resolution; | |
581 float y_resolution; | |
582 | |
583 if (s->line_encoding == T4_COMPRESSION_ITU_T6) | |
584 { | |
585 /* Push enough zeros through the decoder to flush out any remaining codes */ | |
586 for (i = 0; i < 13; i++) | |
587 t4_rx_put_bit(s, 0); | |
588 } | |
589 if (s->curr_bad_row_run) | |
590 { | |
591 if (s->curr_bad_row_run > s->longest_bad_row_run) | |
592 s->longest_bad_row_run = s->curr_bad_row_run; | |
593 s->curr_bad_row_run = 0; | |
594 } | |
595 | |
596 if (s->image_size == 0) | |
597 return -1; | |
598 | |
599 /* Prepare the directory entry fully before writing the image, or libtiff complains */ | |
600 TIFFSetField(s->tiff_file, TIFFTAG_COMPRESSION, s->output_compression); | |
601 if (s->output_compression == COMPRESSION_CCITT_T4) | |
602 { | |
603 TIFFSetField(s->tiff_file, TIFFTAG_T4OPTIONS, s->output_t4_options); | |
604 TIFFSetField(s->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); | |
605 } | |
606 TIFFSetField(s->tiff_file, TIFFTAG_IMAGEWIDTH, s->image_width); | |
607 TIFFSetField(s->tiff_file, TIFFTAG_BITSPERSAMPLE, 1); | |
608 TIFFSetField(s->tiff_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); | |
609 TIFFSetField(s->tiff_file, TIFFTAG_SAMPLESPERPIXEL, 1); | |
610 if (s->output_compression == COMPRESSION_CCITT_T4 | |
611 || | |
612 s->output_compression == COMPRESSION_CCITT_T6) | |
613 { | |
614 TIFFSetField(s->tiff_file, TIFFTAG_ROWSPERSTRIP, -1L); | |
615 } | |
616 else | |
617 { | |
618 TIFFSetField(s->tiff_file, | |
619 TIFFTAG_ROWSPERSTRIP, | |
620 TIFFDefaultStripSize(s->tiff_file, 0)); | |
621 } | |
622 TIFFSetField(s->tiff_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); | |
623 TIFFSetField(s->tiff_file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); | |
624 TIFFSetField(s->tiff_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); | |
625 | |
626 x_resolution = s->x_resolution/100.0f; | |
627 y_resolution = s->y_resolution/100.0f; | |
628 /* Metric seems the sane things to use in the 21st century, but a lot of lousy software | |
629 gets FAX resolutions wrong, and more get it wrong using metric than using inches. */ | |
630 #if 0 | |
631 TIFFSetField(s->tiff_file, TIFFTAG_XRESOLUTION, x_resolution); | |
632 TIFFSetField(s->tiff_file, TIFFTAG_YRESOLUTION, y_resolution); | |
633 resunit = RESUNIT_CENTIMETER; | |
634 TIFFSetField(s->tiff_file, TIFFTAG_RESOLUTIONUNIT, resunit); | |
635 #else | |
636 TIFFSetField(s->tiff_file, TIFFTAG_XRESOLUTION, floorf(x_resolution*2.54f + 0.5f)); | |
637 TIFFSetField(s->tiff_file, TIFFTAG_YRESOLUTION, floorf(y_resolution*2.54f + 0.5f)); | |
638 resunit = RESUNIT_INCH; | |
639 TIFFSetField(s->tiff_file, TIFFTAG_RESOLUTIONUNIT, resunit); | |
640 #endif | |
641 | |
642 /* TODO: add the version of spandsp */ | |
643 TIFFSetField(s->tiff_file, TIFFTAG_SOFTWARE, "spandsp"); | |
644 if (gethostname(buf, sizeof(buf)) == 0) | |
645 TIFFSetField(s->tiff_file, TIFFTAG_HOSTCOMPUTER, buf); | |
646 | |
647 //TIFFSetField(s->tiff_file, TIFFTAG_FAXRECVPARAMS, ???); | |
648 //TIFFSetField(s->tiff_file, TIFFTAG_FAXMODE, ???); | |
649 if (s->sub_address) | |
650 TIFFSetField(s->tiff_file, TIFFTAG_FAXSUBADDRESS, s->sub_address); | |
651 if (s->far_ident) | |
652 TIFFSetField(s->tiff_file, TIFFTAG_IMAGEDESCRIPTION, s->far_ident); | |
653 if (s->vendor) | |
654 TIFFSetField(s->tiff_file, TIFFTAG_MAKE, s->vendor); | |
655 if (s->model) | |
656 TIFFSetField(s->tiff_file, TIFFTAG_MODEL, s->model); | |
657 | |
658 time(&now); | |
659 tm = localtime(&now); | |
660 sprintf(buf, | |
661 "%4d/%02d/%02d %02d:%02d:%02d", | |
662 tm->tm_year + 1900, | |
663 tm->tm_mon + 1, | |
664 tm->tm_mday, | |
665 tm->tm_hour, | |
666 tm->tm_min, | |
667 tm->tm_sec); | |
668 TIFFSetField(s->tiff_file, TIFFTAG_DATETIME, buf); | |
669 TIFFSetField(s->tiff_file, TIFFTAG_FAXRECVTIME, now - s->page_start_time); | |
670 | |
671 TIFFSetField(s->tiff_file, TIFFTAG_IMAGELENGTH, s->image_length); | |
672 /* Set the total pages to 1. For any one page document we will get this | |
673 right. For multi-page documents we will need to come back and fill in | |
674 the right answer when we know it. */ | |
675 TIFFSetField(s->tiff_file, TIFFTAG_PAGENUMBER, s->pages_transferred++, 1); | |
676 if (s->output_compression == COMPRESSION_CCITT_T4) | |
677 { | |
678 if (s->bad_rows) | |
679 { | |
680 TIFFSetField(s->tiff_file, TIFFTAG_BADFAXLINES, s->bad_rows); | |
681 TIFFSetField(s->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_REGENERATED); | |
682 TIFFSetField(s->tiff_file, TIFFTAG_CONSECUTIVEBADFAXLINES, s->longest_bad_row_run); | |
683 } | |
684 else | |
685 { | |
686 TIFFSetField(s->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN); | |
687 } | |
688 } | |
689 TIFFSetField(s->tiff_file, TIFFTAG_IMAGEWIDTH, s->image_width); | |
690 | |
691 /* Write the image first.... */ | |
692 for (row = 0; row < s->image_length; row++) | |
693 { | |
694 if (TIFFWriteScanline(s->tiff_file, s->image_buffer + row*s->bytes_per_row, row, 0) < 0) | |
695 { | |
696 span_log(&s->logging, SPAN_LOG_WARNING, "%s: Write error at row %d.\n", s->file, row); | |
697 break; | |
698 } | |
699 } | |
700 /* ....then the directory entry, and libtiff is happy. */ | |
701 TIFFWriteDirectory(s->tiff_file); | |
702 | |
703 s->bits = 0; | |
704 s->bits_to_date = 0; | |
705 s->consecutive_eols = 0; | |
706 | |
707 s->image_size = 0; | |
708 return 0; | |
709 } | |
710 /*- End of function --------------------------------------------------------*/ | |
711 | |
712 int t4_rx_put_bit(t4_state_t *s, int bit) | |
713 { | |
714 int bits; | |
715 | |
716 /* We decompress bit by bit, as the data stream is received. We need to | |
717 scan continuously for EOLs, so we might as well work this way. */ | |
718 s->bits_to_date = (s->bits_to_date >> 1) | ((bit & 1) << 12); | |
719 if (++s->bits < 13) | |
720 return FALSE; | |
721 if (!s->first_eol_seen) | |
722 { | |
723 /* Do not let anything through to the decoder, until an EOL arrives. */ | |
724 if ((s->bits_to_date & 0xFFF) != 0x800) | |
725 return FALSE; | |
726 s->bits = (s->line_encoding == T4_COMPRESSION_ITU_T4_1D) ? 1 : 0; | |
727 s->first_eol_seen = TRUE; | |
728 return FALSE; | |
729 } | |
730 /* Check if the image has already terminated */ | |
731 if (s->consecutive_eols >= 5) | |
732 return TRUE; | |
733 if (s->row_is_2d && s->black_white == 0) | |
734 { | |
735 switch (T4_black_table[s->bits_to_date & 0x1FFF].state) | |
736 { | |
737 case S_EOL: | |
738 STATE_TRACE("EOL\n"); | |
739 put_eol(s); | |
740 s->row_is_2d = !(s->bits_to_date & 0x1000); | |
741 s->bits -= (T4_black_table[s->bits_to_date & 0x1FFF].width + 1); | |
742 s->its_black = FALSE; | |
743 s->row_len = 0; | |
744 break; | |
745 default: | |
746 bits = s->bits_to_date & 0x7F; | |
747 STATE_TRACE("State %d, %d\n", | |
748 T4_common_table[bits].state, | |
749 T4_common_table[bits].width); | |
750 switch (T4_common_table[bits].state) | |
751 { | |
752 case S_Pass: | |
753 STATE_TRACE("Pass\n"); | |
754 if (s->row_len < s->image_width) | |
755 { | |
756 if (s->pa != s->cur_runs) | |
757 { | |
758 while (s->b1 <= s->a0 && s->b1 < s->image_width) | |
759 { | |
760 s->b1 += s->pb[0] + s->pb[1]; | |
761 s->pb += 2; | |
762 } | |
763 } | |
764 s->b1 += *s->pb++; | |
765 s->run_length += (s->b1 - s->a0); | |
766 s->a0 = s->b1; | |
767 s->b1 += *s->pb++; | |
768 } | |
769 break; | |
770 case S_Horiz: | |
771 STATE_TRACE("Horiz\n"); | |
772 s->its_black = ((int) (s->pa - s->cur_runs)) & 1; | |
773 s->black_white = 2; | |
774 break; | |
775 case S_V0: | |
776 STATE_TRACE("V0 %d %d %d %d\n", | |
777 s->a0, | |
778 s->b1, | |
779 s->image_width, | |
780 s->run_length); | |
781 if (s->row_len < s->image_width) | |
782 { | |
783 if (s->pa != s->cur_runs) | |
784 { | |
785 while (s->b1 <= s->a0 && s->b1 < s->image_width) | |
786 { | |
787 s->b1 += s->pb[0] + s->pb[1]; | |
788 s->pb += 2; | |
789 } | |
790 } | |
791 s->run_length += (s->b1 - s->a0); | |
792 s->a0 = s->b1; | |
793 put_run(s, ((int) (s->pa - s->cur_runs)) & 1); | |
794 s->b1 += *s->pb++; | |
795 } | |
796 break; | |
797 case S_VR: | |
798 STATE_TRACE("VR[%d] %d %d %d %d\n", | |
799 T4_common_table[bits].param, | |
800 s->a0, | |
801 s->b1, | |
802 s->image_width, | |
803 s->run_length); | |
804 if (s->row_len < s->image_width) | |
805 { | |
806 if (s->pa != s->cur_runs) | |
807 { | |
808 while (s->b1 <= s->a0 && s->b1 < s->image_width) | |
809 { | |
810 s->b1 += s->pb[0] + s->pb[1]; | |
811 s->pb += 2; | |
812 } | |
813 } | |
814 s->run_length += (s->b1 + T4_common_table[bits].param - s->a0); | |
815 s->a0 = s->b1 + T4_common_table[bits].param; | |
816 put_run(s, ((int) (s->pa - s->cur_runs)) & 1); | |
817 s->b1 += *s->pb++; | |
818 } | |
819 break; | |
820 case S_VL: | |
821 STATE_TRACE("VL[%d] %d %d %d %d\n", | |
822 T4_common_table[bits].param, | |
823 s->a0, | |
824 s->b1, | |
825 s->image_width, | |
826 s->run_length); | |
827 if (s->row_len < s->image_width) | |
828 { | |
829 if (s->pa != s->cur_runs) | |
830 { | |
831 while (s->b1 <= s->a0 && s->b1 < s->image_width) | |
832 { | |
833 s->b1 += s->pb[0] + s->pb[1]; | |
834 s->pb += 2; | |
835 } | |
836 } | |
837 s->run_length += (s->b1 - T4_common_table[bits].param - s->a0); | |
838 s->a0 = s->b1 - T4_common_table[bits].param; | |
839 put_run(s, ((int) (s->pa - s->cur_runs)) & 1); | |
840 s->b1 -= *--s->pb; | |
841 } | |
842 break; | |
843 case S_Ext: | |
844 STATE_TRACE("Ext %d 0x%x\n", | |
845 ((s->bits_to_date >> T4_common_table[bits].width) & 0x7), | |
846 s->bits_to_date); | |
847 if (s->row_len < s->image_width) | |
848 *s->pa++ = s->image_width - s->a0; | |
849 break; | |
850 case S_Null: | |
851 break; | |
852 default: | |
853 span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected T.4 state %d\n", T4_common_table[bits].state); | |
854 break; | |
855 } | |
856 s->bits -= T4_common_table[bits].width; | |
857 break; | |
858 } | |
859 } | |
860 else | |
861 { | |
862 if (s->its_black) | |
863 { | |
864 bits = s->bits_to_date & 0x1FFF; | |
865 STATE_TRACE("Black state %d %d\n", T4_black_table[bits].state, T4_black_table[bits].param); | |
866 switch (T4_black_table[bits].state) | |
867 { | |
868 case S_MakeUpB: | |
869 case S_MakeUp: | |
870 if (s->row_len < s->image_width) | |
871 { | |
872 s->run_length += T4_black_table[bits].param; | |
873 s->a0 += T4_black_table[bits].param; | |
874 } | |
875 break; | |
876 case S_TermB: | |
877 if (s->row_len < s->image_width) | |
878 { | |
879 s->run_length += T4_black_table[bits].param; | |
880 s->a0 += T4_black_table[bits].param; | |
881 put_run(s, 1); | |
882 if (s->black_white) | |
883 { | |
884 if (s->black_white == 1) | |
885 { | |
886 if (s->pa != s->cur_runs) | |
887 { | |
888 while (s->b1 <= s->a0 && s->b1 < s->image_width) | |
889 { | |
890 s->b1 += s->pb[0] + s->pb[1]; | |
891 s->pb += 2; | |
892 } | |
893 } | |
894 } | |
895 s->black_white--; | |
896 } | |
897 } | |
898 s->its_black = FALSE; | |
899 break; | |
900 case S_EOL: | |
901 STATE_TRACE("EOL\n"); | |
902 if (s->row_len == 0) | |
903 { | |
904 if (++s->consecutive_eols >= 5) | |
905 return TRUE; | |
906 } | |
907 else | |
908 { | |
909 s->consecutive_eols = 0; | |
910 put_eol(s); | |
911 } | |
912 if (s->line_encoding != T4_COMPRESSION_ITU_T4_1D) | |
913 { | |
914 s->row_is_2d = !(s->bits_to_date & 0x1000); | |
915 s->bits--; | |
916 } | |
917 s->its_black = FALSE; | |
918 s->row_len = 0; | |
919 break; | |
920 default: | |
921 /* Bad black */ | |
922 s->black_white = 0; | |
923 break; | |
924 } | |
925 s->bits -= T4_black_table[bits].width; | |
926 } | |
927 else | |
928 { | |
929 bits = s->bits_to_date & 0xFFF; | |
930 STATE_TRACE("White state %d %d\n", T4_white_table[bits].state, T4_white_table[bits].param); | |
931 switch (T4_white_table[bits].state) | |
932 { | |
933 case S_MakeUpW: | |
934 case S_MakeUp: | |
935 if (s->row_len < s->image_width) | |
936 { | |
937 s->run_length += T4_white_table[bits].param; | |
938 s->a0 += T4_white_table[bits].param; | |
939 } | |
940 break; | |
941 case S_TermW: | |
942 if (s->row_len < s->image_width) | |
943 { | |
944 s->run_length += T4_white_table[bits].param; | |
945 s->a0 += T4_white_table[bits].param; | |
946 put_run(s, 0); | |
947 if (s->black_white) | |
948 { | |
949 if (s->black_white == 1) | |
950 { | |
951 if (s->pa != s->cur_runs) | |
952 { | |
953 while (s->b1 <= s->a0 && s->b1 < s->image_width) | |
954 { | |
955 s->b1 += s->pb[0] + s->pb[1]; | |
956 s->pb += 2; | |
957 } | |
958 } | |
959 } | |
960 s->black_white--; | |
961 } | |
962 } | |
963 s->its_black = TRUE; | |
964 break; | |
965 case S_EOL: | |
966 STATE_TRACE("EOL\n"); | |
967 if (s->row_len == 0) | |
968 { | |
969 if (++s->consecutive_eols >= 5) | |
970 return TRUE; | |
971 } | |
972 else | |
973 { | |
974 s->consecutive_eols = 0; | |
975 put_eol(s); | |
976 } | |
977 if (s->line_encoding != T4_COMPRESSION_ITU_T4_1D) | |
978 { | |
979 s->row_is_2d = !(s->bits_to_date & 0x1000); | |
980 s->bits--; | |
981 } | |
982 s->its_black = FALSE; | |
983 s->row_len = 0; | |
984 break; | |
985 default: | |
986 /* Bad white */ | |
987 s->black_white = 0; | |
988 break; | |
989 } | |
990 s->bits -= T4_white_table[bits].width; | |
991 } | |
992 } | |
993 | |
994 if (s->line_encoding == T4_COMPRESSION_ITU_T6 && s->row_len >= s->image_width) | |
995 { | |
996 /* T.6 has no EOL markers. We sense the end of a line by its length alone. */ | |
997 STATE_TRACE("EOL T.6\n"); | |
998 put_eol(s); | |
999 s->its_black = FALSE; | |
1000 s->row_len = 0; | |
1001 } | |
1002 return FALSE; | |
1003 } | |
1004 /*- End of function --------------------------------------------------------*/ | |
1005 | |
1006 t4_state_t *t4_rx_create(const char *file, int output_encoding) | |
1007 { | |
1008 t4_state_t *s; | |
1009 | |
1010 if ((s = (t4_state_t *) malloc(sizeof(t4_state_t *)))) | |
1011 { | |
1012 if (t4_rx_init(s, file, output_encoding)) | |
1013 { | |
1014 free(s); | |
1015 return NULL; | |
1016 } | |
1017 } | |
1018 return s; | |
1019 } | |
1020 /*- End of function --------------------------------------------------------*/ | |
1021 | |
1022 int t4_rx_init(t4_state_t *s, const char *file, int output_encoding) | |
1023 { | |
1024 memset(s, 0, sizeof(*s)); | |
1025 span_log_init(&s->logging, SPAN_LOG_NONE, NULL); | |
1026 span_log_set_protocol(&s->logging, "T.4"); | |
1027 | |
1028 span_log(&s->logging, SPAN_LOG_FLOW, "Start rx document\n"); | |
1029 | |
1030 if ((s->tiff_file = TIFFOpen(file, "w")) == NULL) | |
1031 return -1; | |
1032 | |
1033 /* Save the file name for logging reports. */ | |
1034 s->file = strdup(file); | |
1035 /* Only provide for one form of coding throughout the file, even though the | |
1036 coding on the wire could change between pages. */ | |
1037 switch (output_encoding) | |
1038 { | |
1039 case T4_COMPRESSION_ITU_T4_1D: | |
1040 s->output_compression = COMPRESSION_CCITT_T4; | |
1041 s->output_t4_options = GROUP3OPT_FILLBITS; | |
1042 break; | |
1043 case T4_COMPRESSION_ITU_T4_2D: | |
1044 s->output_compression = COMPRESSION_CCITT_T4; | |
1045 s->output_t4_options = GROUP3OPT_FILLBITS | GROUP3OPT_2DENCODING; | |
1046 break; | |
1047 case T4_COMPRESSION_ITU_T6: | |
1048 s->output_compression = COMPRESSION_CCITT_T6; | |
1049 s->output_t4_options = 0; | |
1050 break; | |
1051 } | |
1052 | |
1053 /* Until we have a valid figure for the bytes per row, we need it to be set to a suitable | |
1054 value to ensure it will be seen as changing when the real value is used. */ | |
1055 s->bytes_per_row = 0; | |
1056 | |
1057 s->pages_transferred = 0; | |
1058 | |
1059 s->image_buffer = NULL; | |
1060 s->image_buffer_size = 0; | |
1061 | |
1062 /* Set some default values */ | |
1063 s->x_resolution = T4_X_RESOLUTION_R8; | |
1064 s->y_resolution = T4_Y_RESOLUTION_FINE; | |
1065 s->image_width = 1728; | |
1066 | |
1067 return 0; | |
1068 } | |
1069 /*- End of function --------------------------------------------------------*/ | |
1070 | |
1071 int t4_rx_start_page(t4_state_t *s) | |
1072 { | |
1073 int bytes_per_row; | |
1074 int run_space; | |
1075 uint32_t *bufptr; | |
1076 | |
1077 span_log(&s->logging, SPAN_LOG_FLOW, "Start rx page - compression %d\n", s->line_encoding); | |
1078 if (s->tiff_file == NULL) | |
1079 return -1; | |
1080 | |
1081 /* Calculate the scanline/tile width. */ | |
1082 bytes_per_row = s->image_width/8; | |
1083 run_space = 2*((s->image_width + 31) & ~31); | |
1084 run_space = (run_space + 3)*sizeof(uint32_t); | |
1085 if (bytes_per_row != s->bytes_per_row) | |
1086 { | |
1087 /* Allocate the space required for decoding the new row length. */ | |
1088 s->bytes_per_row = bytes_per_row; | |
1089 if ((bufptr = (uint32_t *) realloc(s->cur_runs, run_space)) == NULL) | |
1090 return -1; | |
1091 s->cur_runs = bufptr; | |
1092 if ((bufptr = (uint32_t *) realloc(s->ref_runs, run_space)) == NULL) | |
1093 return -1; | |
1094 s->ref_runs = bufptr; | |
1095 } | |
1096 memset(s->cur_runs, 0, run_space); | |
1097 memset(s->ref_runs, 0, run_space); | |
1098 | |
1099 s->bits = 0; | |
1100 s->bits_to_date = 0; | |
1101 | |
1102 s->row_is_2d = (s->line_encoding == T4_COMPRESSION_ITU_T6); | |
1103 s->first_eol_seen = (s->line_encoding == T4_COMPRESSION_ITU_T6); | |
1104 | |
1105 s->bad_rows = 0; | |
1106 s->longest_bad_row_run = 0; | |
1107 s->curr_bad_row_run = 0; | |
1108 s->image_length = 0; | |
1109 s->consecutive_eols = 0; | |
1110 s->data = 0; | |
1111 s->bit = 8; | |
1112 s->image_size = 0; | |
1113 s->row_starts_at = 0; | |
1114 s->last_row_starts_at = 0; | |
1115 | |
1116 s->row_len = 0; | |
1117 s->its_black = FALSE; | |
1118 s->black_white = 0; | |
1119 | |
1120 s->pa = s->cur_runs; | |
1121 s->pb = s->ref_runs; | |
1122 | |
1123 /* Initialise the reference line to all white */ | |
1124 s->ref_runs[0] = s->image_width; | |
1125 s->ref_runs[1] = 0; | |
1126 s->a0 = 0; | |
1127 s->b1 = s->image_width; | |
1128 s->run_length = 0; | |
1129 | |
1130 time (&s->page_start_time); | |
1131 | |
1132 return 0; | |
1133 } | |
1134 /*- End of function --------------------------------------------------------*/ | |
1135 | |
1136 int t4_rx_delete(t4_state_t *s) | |
1137 { | |
1138 if (t4_rx_end(s)) | |
1139 return -1; | |
1140 free(s); | |
1141 return 0; | |
1142 } | |
1143 /*- End of function --------------------------------------------------------*/ | |
1144 | |
1145 int t4_rx_end(t4_state_t *s) | |
1146 { | |
1147 int i; | |
1148 | |
1149 if (s->tiff_file) | |
1150 { | |
1151 if (s->pages_transferred > 1) | |
1152 { | |
1153 /* We need to edit the TIFF directories. Until now we did not know | |
1154 the total page count, so the TIFF file currently says one. Now we | |
1155 need to set the correct total page count associated with each page. */ | |
1156 for (i = 0; i < s->pages_transferred; i++) | |
1157 { | |
1158 TIFFSetDirectory(s->tiff_file, (tdir_t) i); | |
1159 TIFFSetField(s->tiff_file, TIFFTAG_PAGENUMBER, i, s->pages_transferred); | |
1160 TIFFWriteDirectory(s->tiff_file); | |
1161 } | |
1162 } | |
1163 TIFFClose(s->tiff_file); | |
1164 s->tiff_file = NULL; | |
1165 if (s->file) | |
1166 free((char *) s->file); | |
1167 s->file = NULL; | |
1168 } | |
1169 if (s->image_buffer) | |
1170 { | |
1171 free(s->image_buffer); | |
1172 s->image_buffer = NULL; | |
1173 s->image_buffer_size = 0; | |
1174 } | |
1175 if (s->cur_runs) | |
1176 { | |
1177 free(s->cur_runs); | |
1178 s->cur_runs = NULL; | |
1179 } | |
1180 if (s->ref_runs) | |
1181 { | |
1182 free(s->ref_runs); | |
1183 s->ref_runs = NULL; | |
1184 } | |
1185 return 0; | |
1186 } | |
1187 /*- End of function --------------------------------------------------------*/ | |
1188 | |
1189 void t4_rx_set_rx_encoding(t4_state_t *s, int encoding) | |
1190 { | |
1191 s->line_encoding = encoding; | |
1192 } | |
1193 /*- End of function --------------------------------------------------------*/ | |
1194 | |
1195 void t4_rx_set_image_width(t4_state_t *s, int width) | |
1196 { | |
1197 s->image_width = width; | |
1198 } | |
1199 /*- End of function --------------------------------------------------------*/ | |
1200 | |
1201 void t4_rx_set_y_resolution(t4_state_t *s, int resolution) | |
1202 { | |
1203 s->y_resolution = resolution; | |
1204 } | |
1205 /*- End of function --------------------------------------------------------*/ | |
1206 | |
1207 void t4_rx_set_x_resolution(t4_state_t *s, int resolution) | |
1208 { | |
1209 s->x_resolution = resolution; | |
1210 } | |
1211 /*- End of function --------------------------------------------------------*/ | |
1212 | |
1213 void t4_rx_set_sub_address(t4_state_t *s, const char *sub_address) | |
1214 { | |
1215 s->sub_address = (sub_address && sub_address[0]) ? sub_address : NULL; | |
1216 } | |
1217 /*- End of function --------------------------------------------------------*/ | |
1218 | |
1219 void t4_rx_set_far_ident(t4_state_t *s, const char *ident) | |
1220 { | |
1221 s->far_ident = (ident && ident[0]) ? ident : NULL; | |
1222 } | |
1223 /*- End of function --------------------------------------------------------*/ | |
1224 | |
1225 void t4_rx_set_vendor(t4_state_t *s, const char *vendor) | |
1226 { | |
1227 s->vendor = vendor; | |
1228 } | |
1229 /*- End of function --------------------------------------------------------*/ | |
1230 | |
1231 void t4_rx_set_model(t4_state_t *s, const char *model) | |
1232 { | |
1233 s->model = model; | |
1234 } | |
1235 /*- End of function --------------------------------------------------------*/ | |
1236 | |
1237 static __inline__ void put_bits(t4_state_t *s, int bits, int length) | |
1238 { | |
1239 static const int msbmask[9] = | |
1240 { | |
1241 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff | |
1242 }; | |
1243 | |
1244 s->row_bits += length; | |
1245 while (length > s->bit) | |
1246 { | |
1247 s->data |= (bits >> (length - s->bit)); | |
1248 length -= s->bit; | |
1249 flush_bits_to_image_buffer(s); | |
1250 } | |
1251 s->data |= ((bits & msbmask[length]) << (s->bit - length)); | |
1252 s->bit -= length; | |
1253 if (s->bit == 0) | |
1254 flush_bits_to_image_buffer(s); | |
1255 } | |
1256 /*- End of function --------------------------------------------------------*/ | |
1257 | |
1258 /* | |
1259 * Write the sequence of codes that describes | |
1260 * the specified span of zero's or one's. The | |
1261 * appropriate table that holds the make-up and | |
1262 * terminating codes is supplied. | |
1263 */ | |
1264 static __inline__ void put_span(t4_state_t *s, int32_t span, const T4_table_entry *tab) | |
1265 { | |
1266 const T4_table_entry *te; | |
1267 | |
1268 te = &tab[63 + (2560 >> 6)]; | |
1269 while (span >= 2560 + 64) | |
1270 { | |
1271 put_bits(s, te->code, te->length); | |
1272 span -= te->runlen; | |
1273 } | |
1274 te = &tab[63 + (span >> 6)]; | |
1275 if (span >= 64) | |
1276 { | |
1277 put_bits(s, te->code, te->length); | |
1278 span -= te->runlen; | |
1279 } | |
1280 put_bits(s, tab[span].code, tab[span].length); | |
1281 } | |
1282 /*- End of function --------------------------------------------------------*/ | |
1283 | |
1284 /* | |
1285 * Find a span of ones or zeros using the supplied | |
1286 * table. The 'base' of the bit string is supplied | |
1287 * along with the start and end bit indices. | |
1288 */ | |
1289 static __inline__ int find0span(uint8_t *bp, int bs, int be) | |
1290 { | |
1291 int bits; | |
1292 int n; | |
1293 int span; | |
1294 unsigned int *lp; | |
1295 | |
1296 bits = be - bs; | |
1297 bp += bs >> 3; | |
1298 /* Check partial byte on LHS. */ | |
1299 if (bits > 0 && (n = (bs & 7))) | |
1300 { | |
1301 span = run_length((*bp << n) & 0xFF); | |
1302 if (span > 8 - n) /* Value too generous */ | |
1303 span = 8 - n; | |
1304 if (span > bits) /* Constrain span to bit range */ | |
1305 span = bits; | |
1306 if (n + span < 8) /* Doesn't extend to edge of byte */ | |
1307 return span; | |
1308 bits -= span; | |
1309 bp++; | |
1310 } | |
1311 else | |
1312 { | |
1313 span = 0; | |
1314 } | |
1315 if (bits >= (int) (2*8*sizeof(unsigned int))) | |
1316 { | |
1317 /* Align to natural integer boundary and check integers. */ | |
1318 while (!is_aligned(bp, unsigned int)) | |
1319 { | |
1320 if (*bp) | |
1321 return span + run_length(*bp); | |
1322 span += 8; | |
1323 bits -= 8; | |
1324 bp++; | |
1325 } | |
1326 lp = (unsigned int *) bp; | |
1327 while (bits >= (int) (8*sizeof(unsigned int)) && *lp == 0) | |
1328 { | |
1329 span += 8*sizeof(unsigned int); | |
1330 bits -= 8*sizeof(unsigned int); | |
1331 lp++; | |
1332 } | |
1333 bp = (uint8_t *) lp; | |
1334 } | |
1335 /* Scan full bytes for all 0's. */ | |
1336 while (bits >= 8) | |
1337 { | |
1338 if (*bp) | |
1339 return span + run_length(*bp); | |
1340 span += 8; | |
1341 bits -= 8; | |
1342 bp++; | |
1343 } | |
1344 /* Check partial byte on RHS. */ | |
1345 if (bits > 0) | |
1346 { | |
1347 n = run_length(*bp); | |
1348 span += ((n > bits) ? bits : n); | |
1349 } | |
1350 return span; | |
1351 } | |
1352 /*- End of function --------------------------------------------------------*/ | |
1353 | |
1354 static __inline__ int find1span(uint8_t *bp, int bs, int be) | |
1355 { | |
1356 int bits; | |
1357 int n; | |
1358 int span; | |
1359 unsigned int *lp; | |
1360 | |
1361 bits = be - bs; | |
1362 bp += bs >> 3; | |
1363 /* Check partial byte on LHS. */ | |
1364 if (bits > 0 && (n = (bs & 7))) | |
1365 { | |
1366 span = run_length(((*bp << n) & 0xFF) ^ 0xFF); | |
1367 if (span > 8 - n) /* Value too generous */ | |
1368 span = 8 - n; | |
1369 if (span > bits) /* Constrain span to bit range */ | |
1370 span = bits; | |
1371 if (n + span < 8) /* Doesn't extend to edge of byte */ | |
1372 return span; | |
1373 bits -= span; | |
1374 bp++; | |
1375 } | |
1376 else | |
1377 { | |
1378 span = 0; | |
1379 } | |
1380 if (bits >= (int) (2*8*sizeof(unsigned int))) | |
1381 { | |
1382 /* Align to natural integer boundary and check integers. */ | |
1383 while (!is_aligned(bp, unsigned int)) | |
1384 { | |
1385 if (*bp != 0xFF) | |
1386 return span + run_length(*bp ^ 0xFF); | |
1387 span += 8; | |
1388 bits -= 8; | |
1389 bp++; | |
1390 } | |
1391 lp = (unsigned int *) bp; | |
1392 while (bits >= (int) (8*sizeof(unsigned int)) && *lp == (unsigned int) ~0) | |
1393 { | |
1394 span += 8*sizeof(unsigned int); | |
1395 bits -= 8*sizeof(unsigned int); | |
1396 lp++; | |
1397 } | |
1398 bp = (uint8_t *) lp; | |
1399 } | |
1400 /* Scan full bytes for all 1's. */ | |
1401 while (bits >= 8) | |
1402 { | |
1403 if (*bp != 0xFF) | |
1404 return span + run_length(*bp ^ 0xFF); | |
1405 span += 8; | |
1406 bits -= 8; | |
1407 bp++; | |
1408 } | |
1409 /* Check partial byte on RHS. */ | |
1410 if (bits > 0) | |
1411 { | |
1412 n = run_length(*bp ^ 0xFF); | |
1413 span += ((n > bits) ? bits : n); | |
1414 } | |
1415 return span; | |
1416 } | |
1417 /*- End of function --------------------------------------------------------*/ | |
1418 | |
1419 /* | |
1420 * Write an EOL code to the output stream. We also handle writing the tag | |
1421 * bit for the next scanline when doing 2D encoding. | |
1422 */ | |
1423 static void t4_encode_eol(t4_state_t *s) | |
1424 { | |
1425 unsigned int code; | |
1426 int length; | |
1427 | |
1428 if (s->line_encoding == T4_COMPRESSION_ITU_T4_1D) | |
1429 { | |
1430 code = 0x001; | |
1431 length = 12; | |
1432 } | |
1433 else | |
1434 { | |
1435 code = 0x0002 | (!s->row_is_2d); | |
1436 length = 13; | |
1437 } | |
1438 /* We may need to pad the row to a minimum length. */ | |
1439 if (s->row_bits + length < s->min_row_bits) | |
1440 put_bits(s, 0, s->min_row_bits - (s->row_bits + length)); | |
1441 put_bits(s, code, length); | |
1442 s->row_bits = 0; | |
1443 } | |
1444 /*- End of function --------------------------------------------------------*/ | |
1445 | |
1446 /* | |
1447 * 2D-encode a row of pixels. Consult ITU specification T.4 for the algorithm. | |
1448 */ | |
1449 static void t4_encode_2d_row(t4_state_t *s, uint8_t *bp) | |
1450 { | |
1451 int a0; | |
1452 int a1; | |
1453 int b1; | |
1454 int a2; | |
1455 int b2; | |
1456 int d; | |
1457 static const T4_table_entry codes[] = | |
1458 { | |
1459 { 7, 0x03, 0 }, /* VR3 0000 011 */ | |
1460 { 6, 0x03, 0 }, /* VR2 0000 11 */ | |
1461 { 3, 0x03, 0 }, /* VR1 011 */ | |
1462 { 1, 0x01, 0 }, /* V0 1 */ | |
1463 { 3, 0x02, 0 }, /* VL1 010 */ | |
1464 { 6, 0x02, 0 }, /* VL2 0000 10 */ | |
1465 { 7, 0x02, 0 }, /* VL3 0000 010 */ | |
1466 { 3, 0x01, 0 }, /* horizontal 001 */ | |
1467 { 4, 0x01, 0 } /* pass 0001 */ | |
1468 }; | |
1469 | |
1470 a0 = 0; | |
1471 a1 = (bp[0] & 0x80) ? 0 : find0span(bp, 0, s->image_width); | |
1472 b1 = (s->ref_row_buf[0] & 0x80) ? 0 : find0span(s->ref_row_buf, 0, s->image_width); | |
1473 for (;;) | |
1474 { | |
1475 b2 = (b1 < s->image_width) ? (b1 + (((s->ref_row_buf[b1 >> 3] << (b1 & 7)) & 0x80) ? find1span(s->ref_row_buf, b1, s->image_width) : find0span(s->ref_row_buf, b1, s->image_width))) : s->image_width; | |
1476 if (b2 >= a1) | |
1477 { | |
1478 d = b1 - a1; | |
1479 if (-3 <= d && d <= 3) | |
1480 { | |
1481 /* Vertical mode */ | |
1482 put_bits(s, codes[d + 3].code, codes[d + 3].length); | |
1483 a0 = a1; | |
1484 } | |
1485 else | |
1486 { | |
1487 /* Horizontal mode */ | |
1488 a2 = (a1 < s->image_width) ? (a1 + (((bp[a1 >> 3] << (a1 & 7)) & 0x80) ? find1span(bp, a1, s->image_width) : find0span(bp, a1, s->image_width))) : s->image_width; | |
1489 put_bits(s, codes[7].code, codes[7].length); | |
1490 if (a0 + a1 == 0 || ((bp[a0 >> 3] << (a0 & 7)) & 0x80) == 0) | |
1491 { | |
1492 put_span(s, a1 - a0, t4_white_codes); | |
1493 put_span(s, a2 - a1, t4_black_codes); | |
1494 } | |
1495 else | |
1496 { | |
1497 put_span(s, a1 - a0, t4_black_codes); | |
1498 put_span(s, a2 - a1, t4_white_codes); | |
1499 } | |
1500 a0 = a2; | |
1501 } | |
1502 } | |
1503 else | |
1504 { | |
1505 /* Pass mode */ | |
1506 put_bits(s, codes[8].code, codes[8].length); | |
1507 a0 = b2; | |
1508 } | |
1509 if (a0 >= s->image_width) | |
1510 break; | |
1511 a1 = a0 + (((bp[a0 >> 3] << (a0 & 7)) & 0x80) ? find1span(bp, a0, s->image_width) : find0span(bp, a0, s->image_width)); | |
1512 b1 = a0 + (((bp[a0 >> 3] << (a0 & 7)) & 0x80) ? find0span(s->ref_row_buf, a0, s->image_width) : find1span(s->ref_row_buf, a0, s->image_width)); | |
1513 b1 = b1 + (((bp[a0 >> 3] << (a0 & 7)) & 0x80) ? find1span(s->ref_row_buf, b1, s->image_width) : find0span(s->ref_row_buf, b1, s->image_width)); | |
1514 } | |
1515 } | |
1516 /*- End of function --------------------------------------------------------*/ | |
1517 | |
1518 /* | |
1519 * 1D-encode a row of pixels. The encoding is | |
1520 * a sequence of all-white or all-black spans | |
1521 * of pixels encoded with Huffman codes. | |
1522 */ | |
1523 static void t4_encode_1d_row(t4_state_t *s, uint8_t *bp) | |
1524 { | |
1525 int span; | |
1526 int bs; | |
1527 | |
1528 bs = 0; | |
1529 for (;;) | |
1530 { | |
1531 span = find0span(bp, bs, s->image_width); /* white span */ | |
1532 put_span(s, span, t4_white_codes); | |
1533 bs += span; | |
1534 if (bs >= s->image_width) | |
1535 break; | |
1536 span = find1span(bp, bs, s->image_width); /* black span */ | |
1537 put_span(s, span, t4_black_codes); | |
1538 bs += span; | |
1539 if (bs >= s->image_width) | |
1540 break; | |
1541 } | |
1542 } | |
1543 /*- End of function --------------------------------------------------------*/ | |
1544 | |
1545 static int t4_encode_row(t4_state_t *s, uint8_t *bp) | |
1546 { | |
1547 switch (s->line_encoding) | |
1548 { | |
1549 case T4_COMPRESSION_ITU_T6: | |
1550 /* T.6 compression is a trivial step up from T.4 2D, so we just | |
1551 throw it in here. T.6 is only used with error correction, | |
1552 so it does not need independantly compressed (i.e. 1D) lines | |
1553 to recover from data errors. It doesn't need EOLs, either. */ | |
1554 t4_encode_2d_row(s, bp); | |
1555 memcpy(s->ref_row_buf, bp, s->bytes_per_row); | |
1556 break; | |
1557 case T4_COMPRESSION_ITU_T4_2D: | |
1558 t4_encode_eol(s); | |
1559 if (s->row_is_2d) | |
1560 { | |
1561 t4_encode_2d_row(s, bp); | |
1562 s->rows_to_next_1d_row--; | |
1563 } | |
1564 else | |
1565 { | |
1566 t4_encode_1d_row(s, bp); | |
1567 s->row_is_2d = TRUE; | |
1568 } | |
1569 if (s->rows_to_next_1d_row <= 0) | |
1570 { | |
1571 /* Insert a row of 1D encoding */ | |
1572 s->row_is_2d = FALSE; | |
1573 s->rows_to_next_1d_row = s->max_rows_to_next_1d_row - 1; | |
1574 } | |
1575 else | |
1576 { | |
1577 memcpy(s->ref_row_buf, bp, s->bytes_per_row); | |
1578 } | |
1579 break; | |
1580 default: | |
1581 case T4_COMPRESSION_ITU_T4_1D: | |
1582 t4_encode_eol(s); | |
1583 t4_encode_1d_row(s, bp); | |
1584 break; | |
1585 } | |
1586 bp += s->bytes_per_row; | |
1587 s->row++; | |
1588 return 1; | |
1589 } | |
1590 /*- End of function --------------------------------------------------------*/ | |
1591 | |
1592 t4_state_t *t4_tx_create(const char *file, int start_page, int stop_page) | |
1593 { | |
1594 t4_state_t *s; | |
1595 | |
1596 if ((s = (t4_state_t *) malloc(sizeof(t4_state_t *)))) | |
1597 { | |
1598 if (t4_tx_init(s, file, start_page, stop_page)) | |
1599 { | |
1600 free(s); | |
1601 return NULL; | |
1602 } | |
1603 } | |
1604 return s; | |
1605 } | |
1606 /*- End of function --------------------------------------------------------*/ | |
1607 | |
1608 int t4_tx_init(t4_state_t *s, const char *file, int start_page, int stop_page) | |
1609 { | |
1610 float x_resolution; | |
1611 float y_resolution; | |
1612 uint16_t res_unit; | |
1613 uint32_t parm; | |
1614 | |
1615 memset(s, 0, sizeof(*s)); | |
1616 span_log_init(&s->logging, SPAN_LOG_NONE, NULL); | |
1617 span_log_set_protocol(&s->logging, "T.4"); | |
1618 | |
1619 span_log(&s->logging, SPAN_LOG_FLOW, "Start tx document\n"); | |
1620 | |
1621 if ((s->tiff_file = TIFFOpen(file, "r")) == NULL) | |
1622 return -1; | |
1623 | |
1624 s->file = strdup(file); | |
1625 s->start_page = (start_page >= 0) ? start_page : 0; | |
1626 s->stop_page = (stop_page >= 0) ? stop_page : INT_MAX; | |
1627 TIFFGetField(s->tiff_file, TIFFTAG_IMAGEWIDTH, &parm); | |
1628 s->image_width = parm; | |
1629 s->bytes_per_row = (s->image_width + 7)/8; | |
1630 TIFFGetField(s->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution); | |
1631 TIFFGetField(s->tiff_file, TIFFTAG_YRESOLUTION, &y_resolution); | |
1632 TIFFGetField(s->tiff_file, TIFFTAG_RESOLUTIONUNIT, &res_unit); | |
1633 | |
1634 /* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the | |
1635 precise value. The other value should be exact. */ | |
1636 if ((res_unit == RESUNIT_CENTIMETER && fabsf(x_resolution - 160.74f) < 2.0f) | |
1637 || | |
1638 (res_unit == RESUNIT_INCH && fabs(x_resolution - 408.0f) < 2.0f)) | |
1639 { | |
1640 s->x_resolution = T4_X_RESOLUTION_R16; | |
1641 } | |
1642 else if ((res_unit == RESUNIT_CENTIMETER && fabsf(x_resolution - 40.19f) < 2.0f) | |
1643 || | |
1644 (res_unit == RESUNIT_INCH && fabs(x_resolution - 102.0f) < 2.0f)) | |
1645 { | |
1646 s->x_resolution = T4_X_RESOLUTION_R4; | |
1647 } | |
1648 else | |
1649 { | |
1650 /* Treat everything else as R8. Most FAXes are this resolution anyway. */ | |
1651 s->x_resolution = T4_X_RESOLUTION_R8; | |
1652 } | |
1653 | |
1654 if ((res_unit == RESUNIT_CENTIMETER && fabsf(y_resolution - 154.0f) < 2.0f) | |
1655 || | |
1656 (res_unit == RESUNIT_INCH && fabsf(y_resolution - 392.0f) < 2.0f)) | |
1657 { | |
1658 s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; | |
1659 s->max_rows_to_next_1d_row = 8; | |
1660 } | |
1661 else if ((res_unit == RESUNIT_CENTIMETER && fabsf(y_resolution - 77.0f) < 2.0f) | |
1662 || | |
1663 (res_unit == RESUNIT_INCH && fabsf(y_resolution - 196.0f) < 2.0f)) | |
1664 { | |
1665 s->y_resolution = T4_Y_RESOLUTION_FINE; | |
1666 s->max_rows_to_next_1d_row = 4; | |
1667 } | |
1668 else | |
1669 { | |
1670 s->y_resolution = T4_Y_RESOLUTION_STANDARD; | |
1671 s->max_rows_to_next_1d_row = 2; | |
1672 } | |
1673 s->rows_to_next_1d_row = s->max_rows_to_next_1d_row - 1; | |
1674 | |
1675 s->pages_transferred = s->start_page; | |
1676 if ((s->row_buf = malloc(s->bytes_per_row)) == NULL) | |
1677 return -1; | |
1678 if ((s->ref_row_buf = malloc(s->bytes_per_row)) == NULL) | |
1679 { | |
1680 free(s->row_buf); | |
1681 s->row_buf = NULL; | |
1682 return -1; | |
1683 } | |
1684 s->image_buffer_size = 0; | |
1685 return 0; | |
1686 } | |
1687 /*- End of function --------------------------------------------------------*/ | |
1688 | |
1689 static void make_header(t4_state_t *s, char *header) | |
1690 { | |
1691 time_t now; | |
1692 struct tm tm; | |
1693 static const char *months[] = | |
1694 { | |
1695 "Jan", | |
1696 "Feb", | |
1697 "Mar", | |
1698 "Apr", | |
1699 "May", | |
1700 "Jun", | |
1701 "Jul", | |
1702 "Aug", | |
1703 "Sep", | |
1704 "Oct", | |
1705 "Nov", | |
1706 "Dec" | |
1707 }; | |
1708 | |
1709 time(&now); | |
1710 tm = *localtime(&now); | |
1711 snprintf(header, | |
1712 132, | |
1713 " %2d-%s-%d %02d:%02d %-50s %-21s p.%d", | |
1714 tm.tm_mday, | |
1715 months[tm.tm_mon], | |
1716 tm.tm_year + 1900, | |
1717 tm.tm_hour, | |
1718 tm.tm_min, | |
1719 s->header_info, | |
1720 s->local_ident, | |
1721 s->pages_transferred + 1); | |
1722 } | |
1723 /*- End of function --------------------------------------------------------*/ | |
1724 | |
1725 int t4_tx_start_page(t4_state_t *s) | |
1726 { | |
1727 int row; | |
1728 int ok; | |
1729 int i; | |
1730 int pattern; | |
1731 int row_bufptr; | |
1732 int parm; | |
1733 char *t; | |
1734 char header[132 + 1]; | |
1735 | |
1736 span_log(&s->logging, SPAN_LOG_FLOW, "Start tx page %d\n", s->pages_transferred); | |
1737 if (s->pages_transferred > s->stop_page) | |
1738 return -1; | |
1739 if (s->tiff_file == NULL) | |
1740 return -1; | |
1741 if (!TIFFSetDirectory(s->tiff_file, (tdir_t) s->pages_transferred)) | |
1742 return -1; | |
1743 s->image_size = 0; | |
1744 s->bit = 8; | |
1745 s->row_is_2d = (s->line_encoding == T4_COMPRESSION_ITU_T6); | |
1746 s->rows_to_next_1d_row = s->max_rows_to_next_1d_row - 1; | |
1747 | |
1748 /* Allow for pages being of different width */ | |
1749 TIFFGetField(s->tiff_file, TIFFTAG_IMAGEWIDTH, &parm); | |
1750 if (parm != s->image_width) | |
1751 { | |
1752 s->image_width = parm; | |
1753 s->bytes_per_row = (s->image_width + 7)/8; | |
1754 if ((s->row_buf = realloc(s->row_buf, s->bytes_per_row)) == NULL) | |
1755 return -1; | |
1756 if ((s->ref_row_buf = realloc(s->ref_row_buf, s->bytes_per_row)) == NULL) | |
1757 { | |
1758 free(s->row_buf); | |
1759 s->row_buf = NULL; | |
1760 return -1; | |
1761 } | |
1762 } | |
1763 memset(s->ref_row_buf, 0, s->bytes_per_row); | |
1764 | |
1765 if (s->header_info && s->header_info[0]) | |
1766 { | |
1767 /* Modify the resulting image to include a header line, typical of hardware FAX machines */ | |
1768 make_header(s, header); | |
1769 for (row = 0; row < 16; row++) | |
1770 { | |
1771 t = header; | |
1772 row_bufptr = 0; | |
1773 for (t = header; *t && row_bufptr <= s->bytes_per_row - 2; t++) | |
1774 { | |
1775 pattern = header_font[(uint8_t) *t][row]; | |
1776 s->row_buf[row_bufptr++] = (uint8_t) (pattern >> 8); | |
1777 s->row_buf[row_bufptr++] = (uint8_t) (pattern & 0xFF); | |
1778 } | |
1779 for ( ; row_bufptr <= s->bytes_per_row; ) | |
1780 s->row_buf[row_bufptr++] = 0; | |
1781 switch (s->y_resolution) | |
1782 { | |
1783 case T4_Y_RESOLUTION_SUPERFINE: | |
1784 if ((ok = t4_encode_row(s, s->row_buf)) <= 0) | |
1785 return -1; | |
1786 if ((ok = t4_encode_row(s, s->row_buf)) <= 0) | |
1787 return -1; | |
1788 /* Fall through */ | |
1789 case T4_Y_RESOLUTION_FINE: | |
1790 if ((ok = t4_encode_row(s, s->row_buf)) <= 0) | |
1791 return -1; | |
1792 /* Fall through */ | |
1793 default: | |
1794 if ((ok = t4_encode_row(s, s->row_buf)) <= 0) | |
1795 return -1; | |
1796 break; | |
1797 } | |
1798 } | |
1799 } | |
1800 TIFFGetField(s->tiff_file, TIFFTAG_IMAGELENGTH, &s->image_length); | |
1801 for (row = 0; row < s->image_length; row++) | |
1802 { | |
1803 if ((ok = TIFFReadScanline(s->tiff_file, s->row_buf, row, 0)) <= 0) | |
1804 { | |
1805 span_log(&s->logging, SPAN_LOG_WARNING, "%s: Write error at row %d.\n", s->file, row); | |
1806 break; | |
1807 } | |
1808 if ((ok = t4_encode_row(s, s->row_buf)) <= 0) | |
1809 return -1; | |
1810 } | |
1811 | |
1812 if (s->line_encoding != T4_COMPRESSION_ITU_T6) | |
1813 { | |
1814 /* Attach a return to control (RTC == 6 x EOLs) to the end of the page */ | |
1815 s->row_is_2d = FALSE; | |
1816 for (i = 0; i < 6; i++) | |
1817 { | |
1818 t4_encode_eol(s); | |
1819 /* Suppress row padding between these EOLs */ | |
1820 s->row_bits = INT_MAX - 1000; | |
1821 } | |
1822 } | |
1823 put_bits(s, 0, 7); | |
1824 s->bit_pos = 7; | |
1825 s->bit_ptr = 0; | |
1826 s->row_bits = 0; | |
1827 | |
1828 return 0; | |
1829 } | |
1830 /*- End of function --------------------------------------------------------*/ | |
1831 | |
1832 int t4_tx_more_pages(t4_state_t *s) | |
1833 { | |
1834 span_log(&s->logging, SPAN_LOG_FLOW, "Checking for the existance of page %d\n", s->pages_transferred + 1); | |
1835 if (s->pages_transferred > s->stop_page) | |
1836 return -1; | |
1837 if (s->tiff_file == NULL) | |
1838 return -1; | |
1839 if (!TIFFSetDirectory(s->tiff_file, (tdir_t) s->pages_transferred + 1)) | |
1840 return -1; | |
1841 return 0; | |
1842 } | |
1843 /*- End of function --------------------------------------------------------*/ | |
1844 | |
1845 int t4_tx_restart_page(t4_state_t *s) | |
1846 { | |
1847 s->bit_pos = 7; | |
1848 s->bit_ptr = 0; | |
1849 s->row_bits = 0; | |
1850 return 0; | |
1851 } | |
1852 /*- End of function --------------------------------------------------------*/ | |
1853 | |
1854 int t4_tx_end_page(t4_state_t *s) | |
1855 { | |
1856 s->pages_transferred++; | |
1857 return 0; | |
1858 } | |
1859 /*- End of function --------------------------------------------------------*/ | |
1860 | |
1861 int t4_tx_get_bit(t4_state_t *s) | |
1862 { | |
1863 int bit; | |
1864 | |
1865 if (s->bit_ptr >= s->image_size) | |
1866 return PUTBIT_END_OF_DATA; | |
1867 bit = (s->image_buffer[s->bit_ptr] >> s->bit_pos) & 1; | |
1868 if (--s->bit_pos < 0) | |
1869 { | |
1870 s->bit_pos = 7; | |
1871 s->bit_ptr++; | |
1872 } | |
1873 return bit; | |
1874 } | |
1875 /*- End of function --------------------------------------------------------*/ | |
1876 | |
1877 int t4_tx_check_bit(t4_state_t *s) | |
1878 { | |
1879 int bit; | |
1880 | |
1881 if (s->bit_ptr >= s->image_size) | |
1882 return PUTBIT_END_OF_DATA; | |
1883 bit = (s->image_buffer[s->bit_ptr] >> s->bit_pos) & 1; | |
1884 return bit; | |
1885 } | |
1886 /*- End of function --------------------------------------------------------*/ | |
1887 | |
1888 int t4_tx_delete(t4_state_t *s) | |
1889 { | |
1890 if (t4_tx_end(s)) | |
1891 return -1; | |
1892 free(s); | |
1893 return 0; | |
1894 } | |
1895 /*- End of function --------------------------------------------------------*/ | |
1896 | |
1897 int t4_tx_end(t4_state_t *s) | |
1898 { | |
1899 if (s->tiff_file) | |
1900 { | |
1901 TIFFClose(s->tiff_file); | |
1902 s->tiff_file = NULL; | |
1903 if (s->file) | |
1904 free((char *) s->file); | |
1905 s->file = NULL; | |
1906 } | |
1907 if (s->image_buffer) | |
1908 { | |
1909 free(s->image_buffer); | |
1910 s->image_buffer = NULL; | |
1911 s->image_buffer_size = 0; | |
1912 } | |
1913 if (s->row_buf) | |
1914 { | |
1915 free(s->row_buf); | |
1916 s->row_buf = NULL; | |
1917 } | |
1918 if (s->ref_row_buf) | |
1919 { | |
1920 free(s->ref_row_buf); | |
1921 s->ref_row_buf = NULL; | |
1922 } | |
1923 return 0; | |
1924 } | |
1925 /*- End of function --------------------------------------------------------*/ | |
1926 | |
1927 void t4_tx_set_tx_encoding(t4_state_t *s, int encoding) | |
1928 { | |
1929 s->line_encoding = encoding; | |
1930 s->rows_to_next_1d_row = s->max_rows_to_next_1d_row - 1; | |
1931 s->row_is_2d = FALSE; | |
1932 } | |
1933 /*- End of function --------------------------------------------------------*/ | |
1934 | |
1935 void t4_tx_set_min_row_bits(t4_state_t *s, int bits) | |
1936 { | |
1937 s->min_row_bits = bits; | |
1938 } | |
1939 /*- End of function --------------------------------------------------------*/ | |
1940 | |
1941 void t4_tx_set_local_ident(t4_state_t *s, const char *ident) | |
1942 { | |
1943 s->local_ident = (ident && ident[0]) ? ident : NULL; | |
1944 } | |
1945 /*- End of function --------------------------------------------------------*/ | |
1946 | |
1947 void t4_tx_set_header_info(t4_state_t *s, const char *info) | |
1948 { | |
1949 s->header_info = (info && info[0]) ? info : NULL; | |
1950 } | |
1951 /*- End of function --------------------------------------------------------*/ | |
1952 | |
1953 int t4_tx_get_y_resolution(t4_state_t *s) | |
1954 { | |
1955 return s->y_resolution; | |
1956 } | |
1957 /*- End of function --------------------------------------------------------*/ | |
1958 | |
1959 int t4_tx_get_x_resolution(t4_state_t *s) | |
1960 { | |
1961 return s->x_resolution; | |
1962 } | |
1963 /*- End of function --------------------------------------------------------*/ | |
1964 | |
1965 int t4_tx_get_image_width(t4_state_t *s) | |
1966 { | |
1967 return s->image_width; | |
1968 } | |
1969 /*- End of function --------------------------------------------------------*/ | |
1970 | |
1971 void t4_get_transfer_statistics(t4_state_t *s, t4_stats_t *t) | |
1972 { | |
1973 t->pages_transferred = s->pages_transferred; | |
1974 t->width = s->image_width; | |
1975 t->length = s->image_length; | |
1976 t->bad_rows = s->bad_rows; | |
1977 t->longest_bad_row_run = s->longest_bad_row_run; | |
1978 t->x_resolution = s->x_resolution; | |
1979 t->y_resolution = s->y_resolution; | |
1980 t->encoding = s->line_encoding; | |
1981 t->image_size = s->image_size; | |
1982 } | |
1983 /*- End of function --------------------------------------------------------*/ | |
1984 | |
1985 const char *t4_encoding_to_str(int encoding) | |
1986 { | |
1987 switch (encoding) | |
1988 { | |
1989 case T4_COMPRESSION_ITU_T4_1D: | |
1990 return "T.4 1-D"; | |
1991 case T4_COMPRESSION_ITU_T4_2D: | |
1992 return "T.4 2-D"; | |
1993 case T4_COMPRESSION_ITU_T6: | |
1994 return "T.6"; | |
1995 } | |
1996 return "???"; | |
1997 } | |
1998 /*- End of function --------------------------------------------------------*/ | |
1999 /*- End of file ------------------------------------------------------------*/ |