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 ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.