Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/t4_tx.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Fri, 25 Jun 2010 15:50:58 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
|---|---|
| 1 //#define T4_STATE_DEBUGGING | |
| 2 /* | |
| 3 * SpanDSP - a series of DSP components for telephony | |
| 4 * | |
| 5 * t4_tx.c - ITU T.4 FAX transmit processing | |
| 6 * | |
| 7 * Written by Steve Underwood <steveu@coppice.org> | |
| 8 * | |
| 9 * Copyright (C) 2003, 2007 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 Lesser General Public License version 2.1, | |
| 15 * as 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 Lesser General Public License for more details. | |
| 21 * | |
| 22 * You should have received a copy of the GNU Lesser General Public | |
| 23 * License 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_tx.c,v 1.13.2.9 2009/12/21 17:18:40 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 | |
| 56 /*! \file */ | |
| 57 | |
| 58 #if defined(HAVE_CONFIG_H) | |
| 59 #include "config.h" | |
| 60 #endif | |
| 61 | |
| 62 #include <stdlib.h> | |
| 63 #include <inttypes.h> | |
| 64 #include <limits.h> | |
| 65 #include <stdio.h> | |
| 66 #include <fcntl.h> | |
| 67 #include <unistd.h> | |
| 68 #include <time.h> | |
| 69 #include <memory.h> | |
| 70 #include <string.h> | |
| 71 #if defined(HAVE_TGMATH_H) | |
| 72 #include <tgmath.h> | |
| 73 #endif | |
| 74 #if defined(HAVE_MATH_H) | |
| 75 #include <math.h> | |
| 76 #endif | |
| 77 #include "floating_fudge.h" | |
| 78 #include <tiffio.h> | |
| 79 | |
| 80 #include "spandsp/telephony.h" | |
| 81 #include "spandsp/logging.h" | |
| 82 #include "spandsp/bit_operations.h" | |
| 83 #include "spandsp/async.h" | |
| 84 #include "spandsp/t4_rx.h" | |
| 85 #include "spandsp/t4_tx.h" | |
| 86 #include "spandsp/version.h" | |
| 87 | |
| 88 #include "spandsp/private/logging.h" | |
| 89 #include "spandsp/private/t4_rx.h" | |
| 90 #include "spandsp/private/t4_tx.h" | |
| 91 | |
| 92 /*! The number of centimetres in one inch */ | |
| 93 #define CM_PER_INCH 2.54f | |
| 94 | |
| 95 /*! The number of EOLs to be sent at the end of a T.4 page */ | |
| 96 #define EOLS_TO_END_T4_TX_PAGE 6 | |
| 97 /*! The number of EOLs to be sent at the end of a T.6 page */ | |
| 98 #define EOLS_TO_END_T6_TX_PAGE 2 | |
| 99 | |
| 100 #if defined(T4_STATE_DEBUGGING) | |
| 101 static void STATE_TRACE(const char *format, ...) | |
| 102 { | |
| 103 va_list arg_ptr; | |
| 104 | |
| 105 va_start(arg_ptr, format); | |
| 106 vprintf(format, arg_ptr); | |
| 107 va_end(arg_ptr); | |
| 108 } | |
| 109 /*- End of function --------------------------------------------------------*/ | |
| 110 #else | |
| 111 #define STATE_TRACE(...) /**/ | |
| 112 #endif | |
| 113 | |
| 114 /*! T.4 run length table entry */ | |
| 115 typedef struct | |
| 116 { | |
| 117 /*! Length of T.4 code, in bits */ | |
| 118 uint16_t length; | |
| 119 /*! T.4 code */ | |
| 120 uint16_t code; | |
| 121 /*! Run length, in bits */ | |
| 122 int16_t run_length; | |
| 123 } t4_run_table_entry_t; | |
| 124 | |
| 125 #include "faxfont.h" | |
| 126 | |
| 127 /* Legitimate runs of zero bits which are the tail end of one code | |
| 128 plus the start of the next code do not exceed 10 bits. */ | |
| 129 | |
| 130 /* | |
| 131 * Note that these tables are ordered such that the index into the table | |
| 132 * is known to be either the run length, or (run length / 64) + a fixed | |
| 133 * offset. | |
| 134 */ | |
| 135 static const t4_run_table_entry_t t4_white_codes[] = | |
| 136 { | |
| 137 { 8, 0x00AC, 0}, /* 0011 0101 */ | |
| 138 { 6, 0x0038, 1}, /* 0001 11 */ | |
| 139 { 4, 0x000E, 2}, /* 0111 */ | |
| 140 { 4, 0x0001, 3}, /* 1000 */ | |
| 141 { 4, 0x000D, 4}, /* 1011 */ | |
| 142 { 4, 0x0003, 5}, /* 1100 */ | |
| 143 { 4, 0x0007, 6}, /* 1110 */ | |
| 144 { 4, 0x000F, 7}, /* 1111 */ | |
| 145 { 5, 0x0019, 8}, /* 1001 1 */ | |
| 146 { 5, 0x0005, 9}, /* 1010 0 */ | |
| 147 { 5, 0x001C, 10}, /* 0011 1 */ | |
| 148 { 5, 0x0002, 11}, /* 0100 0 */ | |
| 149 { 6, 0x0004, 12}, /* 0010 00 */ | |
| 150 { 6, 0x0030, 13}, /* 0000 11 */ | |
| 151 { 6, 0x000B, 14}, /* 1101 00 */ | |
| 152 { 6, 0x002B, 15}, /* 1101 01 */ | |
| 153 { 6, 0x0015, 16}, /* 1010 10 */ | |
| 154 { 6, 0x0035, 17}, /* 1010 11 */ | |
| 155 { 7, 0x0072, 18}, /* 0100 111 */ | |
| 156 { 7, 0x0018, 19}, /* 0001 100 */ | |
| 157 { 7, 0x0008, 20}, /* 0001 000 */ | |
| 158 { 7, 0x0074, 21}, /* 0010 111 */ | |
| 159 { 7, 0x0060, 22}, /* 0000 011 */ | |
| 160 { 7, 0x0010, 23}, /* 0000 100 */ | |
| 161 { 7, 0x000A, 24}, /* 0101 000 */ | |
| 162 { 7, 0x006A, 25}, /* 0101 011 */ | |
| 163 { 7, 0x0064, 26}, /* 0010 011 */ | |
| 164 { 7, 0x0012, 27}, /* 0100 100 */ | |
| 165 { 7, 0x000C, 28}, /* 0011 000 */ | |
| 166 { 8, 0x0040, 29}, /* 0000 0010 */ | |
| 167 { 8, 0x00C0, 30}, /* 0000 0011 */ | |
| 168 { 8, 0x0058, 31}, /* 0001 1010 */ | |
| 169 { 8, 0x00D8, 32}, /* 0001 1011 */ | |
| 170 { 8, 0x0048, 33}, /* 0001 0010 */ | |
| 171 { 8, 0x00C8, 34}, /* 0001 0011 */ | |
| 172 { 8, 0x0028, 35}, /* 0001 0100 */ | |
| 173 { 8, 0x00A8, 36}, /* 0001 0101 */ | |
| 174 { 8, 0x0068, 37}, /* 0001 0110 */ | |
| 175 { 8, 0x00E8, 38}, /* 0001 0111 */ | |
| 176 { 8, 0x0014, 39}, /* 0010 1000 */ | |
| 177 { 8, 0x0094, 40}, /* 0010 1001 */ | |
| 178 { 8, 0x0054, 41}, /* 0010 1010 */ | |
| 179 { 8, 0x00D4, 42}, /* 0010 1011 */ | |
| 180 { 8, 0x0034, 43}, /* 0010 1100 */ | |
| 181 { 8, 0x00B4, 44}, /* 0010 1101 */ | |
| 182 { 8, 0x0020, 45}, /* 0000 0100 */ | |
| 183 { 8, 0x00A0, 46}, /* 0000 0101 */ | |
| 184 { 8, 0x0050, 47}, /* 0000 1010 */ | |
| 185 { 8, 0x00D0, 48}, /* 0000 1011 */ | |
| 186 { 8, 0x004A, 49}, /* 0101 0010 */ | |
| 187 { 8, 0x00CA, 50}, /* 0101 0011 */ | |
| 188 { 8, 0x002A, 51}, /* 0101 0100 */ | |
| 189 { 8, 0x00AA, 52}, /* 0101 0101 */ | |
| 190 { 8, 0x0024, 53}, /* 0010 0100 */ | |
| 191 { 8, 0x00A4, 54}, /* 0010 0101 */ | |
| 192 { 8, 0x001A, 55}, /* 0101 1000 */ | |
| 193 { 8, 0x009A, 56}, /* 0101 1001 */ | |
| 194 { 8, 0x005A, 57}, /* 0101 1010 */ | |
| 195 { 8, 0x00DA, 58}, /* 0101 1011 */ | |
| 196 { 8, 0x0052, 59}, /* 0100 1010 */ | |
| 197 { 8, 0x00D2, 60}, /* 0100 1011 */ | |
| 198 { 8, 0x004C, 61}, /* 0011 0010 */ | |
| 199 { 8, 0x00CC, 62}, /* 0011 0011 */ | |
| 200 { 8, 0x002C, 63}, /* 0011 0100 */ | |
| 201 { 5, 0x001B, 64}, /* 1101 1 */ | |
| 202 { 5, 0x0009, 128}, /* 1001 0 */ | |
| 203 { 6, 0x003A, 192}, /* 0101 11 */ | |
| 204 { 7, 0x0076, 256}, /* 0110 111 */ | |
| 205 { 8, 0x006C, 320}, /* 0011 0110 */ | |
| 206 { 8, 0x00EC, 384}, /* 0011 0111 */ | |
| 207 { 8, 0x0026, 448}, /* 0110 0100 */ | |
| 208 { 8, 0x00A6, 512}, /* 0110 0101 */ | |
| 209 { 8, 0x0016, 576}, /* 0110 1000 */ | |
| 210 { 8, 0x00E6, 640}, /* 0110 0111 */ | |
| 211 { 9, 0x0066, 704}, /* 0110 0110 0 */ | |
| 212 { 9, 0x0166, 768}, /* 0110 0110 1 */ | |
| 213 { 9, 0x0096, 832}, /* 0110 1001 0 */ | |
| 214 { 9, 0x0196, 896}, /* 0110 1001 1 */ | |
| 215 { 9, 0x0056, 960}, /* 0110 1010 0 */ | |
| 216 { 9, 0x0156, 1024}, /* 0110 1010 1 */ | |
| 217 { 9, 0x00D6, 1088}, /* 0110 1011 0 */ | |
| 218 { 9, 0x01D6, 1152}, /* 0110 1011 1 */ | |
| 219 { 9, 0x0036, 1216}, /* 0110 1100 0 */ | |
| 220 { 9, 0x0136, 1280}, /* 0110 1100 1 */ | |
| 221 { 9, 0x00B6, 1344}, /* 0110 1101 0 */ | |
| 222 { 9, 0x01B6, 1408}, /* 0110 1101 1 */ | |
| 223 { 9, 0x0032, 1472}, /* 0100 1100 0 */ | |
| 224 { 9, 0x0132, 1536}, /* 0100 1100 1 */ | |
| 225 { 9, 0x00B2, 1600}, /* 0100 1101 0 */ | |
| 226 { 6, 0x0006, 1664}, /* 0110 00 */ | |
| 227 { 9, 0x01B2, 1728}, /* 0100 1101 1 */ | |
| 228 {11, 0x0080, 1792}, /* 0000 0001 000 */ | |
| 229 {11, 0x0180, 1856}, /* 0000 0001 100 */ | |
| 230 {11, 0x0580, 1920}, /* 0000 0001 101 */ | |
| 231 {12, 0x0480, 1984}, /* 0000 0001 0010 */ | |
| 232 {12, 0x0C80, 2048}, /* 0000 0001 0011 */ | |
| 233 {12, 0x0280, 2112}, /* 0000 0001 0100 */ | |
| 234 {12, 0x0A80, 2176}, /* 0000 0001 0101 */ | |
| 235 {12, 0x0680, 2240}, /* 0000 0001 0110 */ | |
| 236 {12, 0x0E80, 2304}, /* 0000 0001 0111 */ | |
| 237 {12, 0x0380, 2368}, /* 0000 0001 1100 */ | |
| 238 {12, 0x0B80, 2432}, /* 0000 0001 1101 */ | |
| 239 {12, 0x0780, 2496}, /* 0000 0001 1110 */ | |
| 240 {12, 0x0F80, 2560}, /* 0000 0001 1111 */ | |
| 241 }; | |
| 242 | |
| 243 static const t4_run_table_entry_t t4_black_codes[] = | |
| 244 { | |
| 245 {10, 0x03B0, 0}, /* 0000 1101 11 */ | |
| 246 { 3, 0x0002, 1}, /* 010 */ | |
| 247 { 2, 0x0003, 2}, /* 11 */ | |
| 248 { 2, 0x0001, 3}, /* 10 */ | |
| 249 { 3, 0x0006, 4}, /* 011 */ | |
| 250 { 4, 0x000C, 5}, /* 0011 */ | |
| 251 { 4, 0x0004, 6}, /* 0010 */ | |
| 252 { 5, 0x0018, 7}, /* 0001 1 */ | |
| 253 { 6, 0x0028, 8}, /* 0001 01 */ | |
| 254 { 6, 0x0008, 9}, /* 0001 00 */ | |
| 255 { 7, 0x0010, 10}, /* 0000 100 */ | |
| 256 { 7, 0x0050, 11}, /* 0000 101 */ | |
| 257 { 7, 0x0070, 12}, /* 0000 111 */ | |
| 258 { 8, 0x0020, 13}, /* 0000 0100 */ | |
| 259 { 8, 0x00E0, 14}, /* 0000 0111 */ | |
| 260 { 9, 0x0030, 15}, /* 0000 1100 0 */ | |
| 261 {10, 0x03A0, 16}, /* 0000 0101 11 */ | |
| 262 {10, 0x0060, 17}, /* 0000 0110 00 */ | |
| 263 {10, 0x0040, 18}, /* 0000 0010 00 */ | |
| 264 {11, 0x0730, 19}, /* 0000 1100 111 */ | |
| 265 {11, 0x00B0, 20}, /* 0000 1101 000 */ | |
| 266 {11, 0x01B0, 21}, /* 0000 1101 100 */ | |
| 267 {11, 0x0760, 22}, /* 0000 0110 111 */ | |
| 268 {11, 0x00A0, 23}, /* 0000 0101 000 */ | |
| 269 {11, 0x0740, 24}, /* 0000 0010 111 */ | |
| 270 {11, 0x00C0, 25}, /* 0000 0011 000 */ | |
| 271 {12, 0x0530, 26}, /* 0000 1100 1010 */ | |
| 272 {12, 0x0D30, 27}, /* 0000 1100 1011 */ | |
| 273 {12, 0x0330, 28}, /* 0000 1100 1100 */ | |
| 274 {12, 0x0B30, 29}, /* 0000 1100 1101 */ | |
| 275 {12, 0x0160, 30}, /* 0000 0110 1000 */ | |
| 276 {12, 0x0960, 31}, /* 0000 0110 1001 */ | |
| 277 {12, 0x0560, 32}, /* 0000 0110 1010 */ | |
| 278 {12, 0x0D60, 33}, /* 0000 0110 1011 */ | |
| 279 {12, 0x04B0, 34}, /* 0000 1101 0010 */ | |
| 280 {12, 0x0CB0, 35}, /* 0000 1101 0011 */ | |
| 281 {12, 0x02B0, 36}, /* 0000 1101 0100 */ | |
| 282 {12, 0x0AB0, 37}, /* 0000 1101 0101 */ | |
| 283 {12, 0x06B0, 38}, /* 0000 1101 0110 */ | |
| 284 {12, 0x0EB0, 39}, /* 0000 1101 0111 */ | |
| 285 {12, 0x0360, 40}, /* 0000 0110 1100 */ | |
| 286 {12, 0x0B60, 41}, /* 0000 0110 1101 */ | |
| 287 {12, 0x05B0, 42}, /* 0000 1101 1010 */ | |
| 288 {12, 0x0DB0, 43}, /* 0000 1101 1011 */ | |
| 289 {12, 0x02A0, 44}, /* 0000 0101 0100 */ | |
| 290 {12, 0x0AA0, 45}, /* 0000 0101 0101 */ | |
| 291 {12, 0x06A0, 46}, /* 0000 0101 0110 */ | |
| 292 {12, 0x0EA0, 47}, /* 0000 0101 0111 */ | |
| 293 {12, 0x0260, 48}, /* 0000 0110 0100 */ | |
| 294 {12, 0x0A60, 49}, /* 0000 0110 0101 */ | |
| 295 {12, 0x04A0, 50}, /* 0000 0101 0010 */ | |
| 296 {12, 0x0CA0, 51}, /* 0000 0101 0011 */ | |
| 297 {12, 0x0240, 52}, /* 0000 0010 0100 */ | |
| 298 {12, 0x0EC0, 53}, /* 0000 0011 0111 */ | |
| 299 {12, 0x01C0, 54}, /* 0000 0011 1000 */ | |
| 300 {12, 0x0E40, 55}, /* 0000 0010 0111 */ | |
| 301 {12, 0x0140, 56}, /* 0000 0010 1000 */ | |
| 302 {12, 0x01A0, 57}, /* 0000 0101 1000 */ | |
| 303 {12, 0x09A0, 58}, /* 0000 0101 1001 */ | |
| 304 {12, 0x0D40, 59}, /* 0000 0010 1011 */ | |
| 305 {12, 0x0340, 60}, /* 0000 0010 1100 */ | |
| 306 {12, 0x05A0, 61}, /* 0000 0101 1010 */ | |
| 307 {12, 0x0660, 62}, /* 0000 0110 0110 */ | |
| 308 {12, 0x0E60, 63}, /* 0000 0110 0111 */ | |
| 309 {10, 0x03C0, 64}, /* 0000 0011 11 */ | |
| 310 {12, 0x0130, 128}, /* 0000 1100 1000 */ | |
| 311 {12, 0x0930, 192}, /* 0000 1100 1001 */ | |
| 312 {12, 0x0DA0, 256}, /* 0000 0101 1011 */ | |
| 313 {12, 0x0CC0, 320}, /* 0000 0011 0011 */ | |
| 314 {12, 0x02C0, 384}, /* 0000 0011 0100 */ | |
| 315 {12, 0x0AC0, 448}, /* 0000 0011 0101 */ | |
| 316 {13, 0x06C0, 512}, /* 0000 0011 0110 0 */ | |
| 317 {13, 0x16C0, 576}, /* 0000 0011 0110 1 */ | |
| 318 {13, 0x0A40, 640}, /* 0000 0010 0101 0 */ | |
| 319 {13, 0x1A40, 704}, /* 0000 0010 0101 1 */ | |
| 320 {13, 0x0640, 768}, /* 0000 0010 0110 0 */ | |
| 321 {13, 0x1640, 832}, /* 0000 0010 0110 1 */ | |
| 322 {13, 0x09C0, 896}, /* 0000 0011 1001 0 */ | |
| 323 {13, 0x19C0, 960}, /* 0000 0011 1001 1 */ | |
| 324 {13, 0x05C0, 1024}, /* 0000 0011 1010 0 */ | |
| 325 {13, 0x15C0, 1088}, /* 0000 0011 1010 1 */ | |
| 326 {13, 0x0DC0, 1152}, /* 0000 0011 1011 0 */ | |
| 327 {13, 0x1DC0, 1216}, /* 0000 0011 1011 1 */ | |
| 328 {13, 0x0940, 1280}, /* 0000 0010 1001 0 */ | |
| 329 {13, 0x1940, 1344}, /* 0000 0010 1001 1 */ | |
| 330 {13, 0x0540, 1408}, /* 0000 0010 1010 0 */ | |
| 331 {13, 0x1540, 1472}, /* 0000 0010 1010 1 */ | |
| 332 {13, 0x0B40, 1536}, /* 0000 0010 1101 0 */ | |
| 333 {13, 0x1B40, 1600}, /* 0000 0010 1101 1 */ | |
| 334 {13, 0x04C0, 1664}, /* 0000 0011 0010 0 */ | |
| 335 {13, 0x14C0, 1728}, /* 0000 0011 0010 1 */ | |
| 336 {11, 0x0080, 1792}, /* 0000 0001 000 */ | |
| 337 {11, 0x0180, 1856}, /* 0000 0001 100 */ | |
| 338 {11, 0x0580, 1920}, /* 0000 0001 101 */ | |
| 339 {12, 0x0480, 1984}, /* 0000 0001 0010 */ | |
| 340 {12, 0x0C80, 2048}, /* 0000 0001 0011 */ | |
| 341 {12, 0x0280, 2112}, /* 0000 0001 0100 */ | |
| 342 {12, 0x0A80, 2176}, /* 0000 0001 0101 */ | |
| 343 {12, 0x0680, 2240}, /* 0000 0001 0110 */ | |
| 344 {12, 0x0E80, 2304}, /* 0000 0001 0111 */ | |
| 345 {12, 0x0380, 2368}, /* 0000 0001 1100 */ | |
| 346 {12, 0x0B80, 2432}, /* 0000 0001 1101 */ | |
| 347 {12, 0x0780, 2496}, /* 0000 0001 1110 */ | |
| 348 {12, 0x0F80, 2560}, /* 0000 0001 1111 */ | |
| 349 }; | |
| 350 | |
| 351 static int encode_row(t4_state_t *s); | |
| 352 | |
| 353 static void make_header(t4_state_t *s, char *header) | |
| 354 { | |
| 355 time_t now; | |
| 356 struct tm tm; | |
| 357 static const char *months[] = | |
| 358 { | |
| 359 "Jan", | |
| 360 "Feb", | |
| 361 "Mar", | |
| 362 "Apr", | |
| 363 "May", | |
| 364 "Jun", | |
| 365 "Jul", | |
| 366 "Aug", | |
| 367 "Sep", | |
| 368 "Oct", | |
| 369 "Nov", | |
| 370 "Dec" | |
| 371 }; | |
| 372 | |
| 373 time(&now); | |
| 374 tm = *localtime(&now); | |
| 375 snprintf(header, | |
| 376 132, | |
| 377 " %2d-%s-%d %02d:%02d %-50s %-21s p.%d", | |
| 378 tm.tm_mday, | |
| 379 months[tm.tm_mon], | |
| 380 tm.tm_year + 1900, | |
| 381 tm.tm_hour, | |
| 382 tm.tm_min, | |
| 383 s->t4_t6_tx.header_info, | |
| 384 s->tiff.local_ident, | |
| 385 s->current_page + 1); | |
| 386 } | |
| 387 /*- End of function --------------------------------------------------------*/ | |
| 388 | |
| 389 static int t4_tx_put_fax_header(t4_state_t *s) | |
| 390 { | |
| 391 int row; | |
| 392 int i; | |
| 393 int repeats; | |
| 394 int pattern; | |
| 395 int row_bufptr; | |
| 396 char *t; | |
| 397 char header[132 + 1]; | |
| 398 | |
| 399 /* Modify the resulting image to include a header line, typical of hardware FAX machines */ | |
| 400 make_header(s, header); | |
| 401 switch (s->y_resolution) | |
| 402 { | |
| 403 case T4_Y_RESOLUTION_1200: | |
| 404 repeats = 12; | |
| 405 break; | |
| 406 case T4_Y_RESOLUTION_800: | |
| 407 repeats = 8; | |
| 408 break; | |
| 409 case T4_Y_RESOLUTION_600: | |
| 410 repeats = 6; | |
| 411 break; | |
| 412 case T4_Y_RESOLUTION_SUPERFINE: | |
| 413 repeats = 4; | |
| 414 break; | |
| 415 case T4_Y_RESOLUTION_300: | |
| 416 repeats = 3; | |
| 417 break; | |
| 418 case T4_Y_RESOLUTION_FINE: | |
| 419 repeats = 2; | |
| 420 break; | |
| 421 default: | |
| 422 repeats = 1; | |
| 423 break; | |
| 424 } | |
| 425 for (row = 0; row < 16; row++) | |
| 426 { | |
| 427 t = header; | |
| 428 row_bufptr = 0; | |
| 429 for (t = header; *t && row_bufptr <= s->bytes_per_row - 2; t++) | |
| 430 { | |
| 431 pattern = header_font[(uint8_t) *t][row]; | |
| 432 s->row_buf[row_bufptr++] = (uint8_t) (pattern >> 8); | |
| 433 s->row_buf[row_bufptr++] = (uint8_t) (pattern & 0xFF); | |
| 434 } | |
| 435 for ( ; row_bufptr < s->bytes_per_row; ) | |
| 436 s->row_buf[row_bufptr++] = 0; | |
| 437 for (i = 0; i < repeats; i++) | |
| 438 { | |
| 439 if (encode_row(s)) | |
| 440 return -1; | |
| 441 } | |
| 442 } | |
| 443 return 0; | |
| 444 } | |
| 445 /*- End of function --------------------------------------------------------*/ | |
| 446 | |
| 447 static int test_resolution(int res_unit, float actual, float expected) | |
| 448 { | |
| 449 if (res_unit == RESUNIT_INCH) | |
| 450 actual *= 1.0f/CM_PER_INCH; | |
| 451 return (expected*0.95f <= actual && actual <= expected*1.05f); | |
| 452 } | |
| 453 /*- End of function --------------------------------------------------------*/ | |
| 454 | |
| 455 static int get_tiff_directory_info(t4_state_t *s) | |
| 456 { | |
| 457 static const struct | |
| 458 { | |
| 459 float resolution; | |
| 460 int code; | |
| 461 } x_res_table[] = | |
| 462 { | |
| 463 { 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4}, | |
| 464 { 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8}, | |
| 465 { 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300}, | |
| 466 { 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16}, | |
| 467 { 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600}, | |
| 468 { 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800}, | |
| 469 {1200.0f/CM_PER_INCH, T4_X_RESOLUTION_1200}, | |
| 470 { -1.00f, -1} | |
| 471 }; | |
| 472 static const struct | |
| 473 { | |
| 474 float resolution; | |
| 475 int code; | |
| 476 int max_rows_to_next_1d_row; | |
| 477 } y_res_table[] = | |
| 478 { | |
| 479 { 38.50f, T4_Y_RESOLUTION_STANDARD, 2}, | |
| 480 { 77.00f, T4_Y_RESOLUTION_FINE, 4}, | |
| 481 { 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300, 6}, | |
| 482 { 154.00f, T4_Y_RESOLUTION_SUPERFINE, 8}, | |
| 483 { 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600, 12}, | |
| 484 { 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800, 16}, | |
| 485 {1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200, 24}, | |
| 486 { -1.00f, -1, -1} | |
| 487 }; | |
| 488 uint16_t res_unit; | |
| 489 uint16_t parm16; | |
| 490 uint32_t parm32; | |
| 491 float x_resolution; | |
| 492 float y_resolution; | |
| 493 int i; | |
| 494 t4_tiff_state_t *t; | |
| 495 | |
| 496 t = &s->tiff; | |
| 497 parm16 = 0; | |
| 498 TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16); | |
| 499 if (parm16 != 1) | |
| 500 return -1; | |
| 501 TIFFGetField(t->tiff_file, TIFFTAG_SAMPLESPERPIXEL, &parm16); | |
| 502 if (parm16 != 1) | |
| 503 return -1; | |
| 504 parm32 = 0; | |
| 505 TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32); | |
| 506 s->image_width = parm32; | |
| 507 s->bytes_per_row = (s->image_width + 7)/8; | |
| 508 parm32 = 0; | |
| 509 TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32); | |
| 510 s->image_length = parm32; | |
| 511 x_resolution = 0.0f; | |
| 512 TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution); | |
| 513 y_resolution = 0.0f; | |
| 514 TIFFGetField(t->tiff_file, TIFFTAG_YRESOLUTION, &y_resolution); | |
| 515 res_unit = RESUNIT_INCH; | |
| 516 TIFFGetField(t->tiff_file, TIFFTAG_RESOLUTIONUNIT, &res_unit); | |
| 517 t->photo_metric = PHOTOMETRIC_MINISWHITE; | |
| 518 TIFFGetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, &t->photo_metric); | |
| 519 if (t->photo_metric != PHOTOMETRIC_MINISWHITE) | |
| 520 span_log(&s->logging, SPAN_LOG_FLOW, "%s: Photometric needs swapping.\n", t->file); | |
| 521 t->fill_order = FILLORDER_LSB2MSB; | |
| 522 #if 0 | |
| 523 TIFFGetField(t->tiff_file, TIFFTAG_FILLORDER, &t->fill_order); | |
| 524 if (t->fill_order != FILLORDER_LSB2MSB) | |
| 525 span_log(&s->logging, SPAN_LOG_FLOW, "%s: Fill order needs swapping.\n", t->file); | |
| 526 #endif | |
| 527 | |
| 528 /* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the | |
| 529 precise value. The other value should be exact. */ | |
| 530 /* Treat everything we can't match as R8. Most FAXes are this resolution anyway. */ | |
| 531 s->x_resolution = T4_X_RESOLUTION_R8; | |
| 532 for (i = 0; x_res_table[i].code > 0; i++) | |
| 533 { | |
| 534 if (test_resolution(res_unit, x_resolution, x_res_table[i].resolution)) | |
| 535 { | |
| 536 s->x_resolution = x_res_table[i].code; | |
| 537 break; | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 s->y_resolution = T4_Y_RESOLUTION_STANDARD; | |
| 542 s->t4_t6_tx.max_rows_to_next_1d_row = 2; | |
| 543 for (i = 0; y_res_table[i].code > 0; i++) | |
| 544 { | |
| 545 if (test_resolution(res_unit, y_resolution, y_res_table[i].resolution)) | |
| 546 { | |
| 547 s->y_resolution = y_res_table[i].code; | |
| 548 s->t4_t6_tx.max_rows_to_next_1d_row = y_res_table[i].max_rows_to_next_1d_row; | |
| 549 break; | |
| 550 } | |
| 551 } | |
| 552 | |
| 553 return 0; | |
| 554 } | |
| 555 /*- End of function --------------------------------------------------------*/ | |
| 556 | |
| 557 static int test_tiff_directory_info(t4_state_t *s) | |
| 558 { | |
| 559 static const struct | |
| 560 { | |
| 561 float resolution; | |
| 562 int code; | |
| 563 } x_res_table[] = | |
| 564 { | |
| 565 { 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4}, | |
| 566 { 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8}, | |
| 567 { 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300}, | |
| 568 { 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16}, | |
| 569 { 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600}, | |
| 570 { 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800}, | |
| 571 {1200.0f/CM_PER_INCH, T4_X_RESOLUTION_1200}, | |
| 572 { -1.00f, -1} | |
| 573 }; | |
| 574 static const struct | |
| 575 { | |
| 576 float resolution; | |
| 577 int code; | |
| 578 int max_rows_to_next_1d_row; | |
| 579 } y_res_table[] = | |
| 580 { | |
| 581 { 38.50f, T4_Y_RESOLUTION_STANDARD, 2}, | |
| 582 { 77.00f, T4_Y_RESOLUTION_FINE, 4}, | |
| 583 { 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300, 6}, | |
| 584 { 154.00f, T4_Y_RESOLUTION_SUPERFINE, 8}, | |
| 585 { 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600, 12}, | |
| 586 { 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800, 16}, | |
| 587 {1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200, 24}, | |
| 588 { -1.00f, -1, -1} | |
| 589 }; | |
| 590 uint16_t res_unit; | |
| 591 uint16_t parm16; | |
| 592 uint32_t parm32; | |
| 593 float x_resolution; | |
| 594 float y_resolution; | |
| 595 int i; | |
| 596 t4_tiff_state_t *t; | |
| 597 | |
| 598 t = &s->tiff; | |
| 599 parm16 = 0; | |
| 600 TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16); | |
| 601 if (parm16 != 1) | |
| 602 return -1; | |
| 603 parm32 = 0; | |
| 604 TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32); | |
| 605 if (s->image_width != (int) parm32) | |
| 606 return 1; | |
| 607 x_resolution = 0.0f; | |
| 608 TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution); | |
| 609 y_resolution = 0.0f; | |
| 610 TIFFGetField(t->tiff_file, TIFFTAG_YRESOLUTION, &y_resolution); | |
| 611 res_unit = RESUNIT_INCH; | |
| 612 TIFFGetField(t->tiff_file, TIFFTAG_RESOLUTIONUNIT, &res_unit); | |
| 613 | |
| 614 /* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the | |
| 615 precise value. The other value should be exact. */ | |
| 616 /* Treat everything we can't match as R8. Most FAXes are this resolution anyway. */ | |
| 617 for (i = 0; x_res_table[i].code > 0; i++) | |
| 618 { | |
| 619 if (test_resolution(res_unit, x_resolution, x_res_table[i].resolution)) | |
| 620 break; | |
| 621 } | |
| 622 if (s->x_resolution != x_res_table[i].code) | |
| 623 return 1; | |
| 624 for (i = 0; y_res_table[i].code > 0; i++) | |
| 625 { | |
| 626 if (test_resolution(res_unit, y_resolution, y_res_table[i].resolution)) | |
| 627 break; | |
| 628 } | |
| 629 if (s->y_resolution != y_res_table[i].code) | |
| 630 return 1; | |
| 631 return 0; | |
| 632 } | |
| 633 /*- End of function --------------------------------------------------------*/ | |
| 634 | |
| 635 static int get_tiff_total_pages(t4_state_t *s) | |
| 636 { | |
| 637 int max; | |
| 638 | |
| 639 /* Each page *should* contain the total number of pages, but can this be | |
| 640 trusted? Some files say 0. Actually searching for the last page is | |
| 641 more reliable. */ | |
| 642 max = 0; | |
| 643 while (TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) max)) | |
| 644 max++; | |
| 645 /* Back to the previous page */ | |
| 646 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page)) | |
| 647 return -1; | |
| 648 return max; | |
| 649 } | |
| 650 /*- End of function --------------------------------------------------------*/ | |
| 651 | |
| 652 static int open_tiff_input_file(t4_state_t *s, const char *file) | |
| 653 { | |
| 654 if ((s->tiff.tiff_file = TIFFOpen(file, "r")) == NULL) | |
| 655 return -1; | |
| 656 return 0; | |
| 657 } | |
| 658 /*- End of function --------------------------------------------------------*/ | |
| 659 | |
| 660 static int read_tiff_image(t4_state_t *s) | |
| 661 { | |
| 662 int row; | |
| 663 int image_length; | |
| 664 int i; | |
| 665 | |
| 666 image_length = 0; | |
| 667 TIFFGetField(s->tiff.tiff_file, TIFFTAG_IMAGELENGTH, &image_length); | |
| 668 for (row = 0; row < image_length; row++) | |
| 669 { | |
| 670 if (TIFFReadScanline(s->tiff.tiff_file, s->row_buf, row, 0) <= 0) | |
| 671 { | |
| 672 span_log(&s->logging, SPAN_LOG_WARNING, "%s: Read error at row %d.\n", s->tiff.file, row); | |
| 673 break; | |
| 674 } | |
| 675 if (s->tiff.photo_metric != PHOTOMETRIC_MINISWHITE) | |
| 676 { | |
| 677 for (i = 0; i < s->bytes_per_row; i++) | |
| 678 s->row_buf[i] = ~s->row_buf[i]; | |
| 679 } | |
| 680 if (s->tiff.fill_order != FILLORDER_LSB2MSB) | |
| 681 bit_reverse(s->row_buf, s->row_buf, s->bytes_per_row); | |
| 682 if (encode_row(s)) | |
| 683 return -1; | |
| 684 } | |
| 685 return image_length; | |
| 686 } | |
| 687 /*- End of function --------------------------------------------------------*/ | |
| 688 | |
| 689 static int close_tiff_input_file(t4_state_t *s) | |
| 690 { | |
| 691 TIFFClose(s->tiff.tiff_file); | |
| 692 s->tiff.tiff_file = NULL; | |
| 693 if (s->tiff.file) | |
| 694 free((char *) s->tiff.file); | |
| 695 s->tiff.file = NULL; | |
| 696 return 0; | |
| 697 } | |
| 698 /*- End of function --------------------------------------------------------*/ | |
| 699 | |
| 700 static void update_row_bit_info(t4_state_t *s) | |
| 701 { | |
| 702 if (s->row_bits > s->max_row_bits) | |
| 703 s->max_row_bits = s->row_bits; | |
| 704 if (s->row_bits < s->min_row_bits) | |
| 705 s->min_row_bits = s->row_bits; | |
| 706 s->row_bits = 0; | |
| 707 } | |
| 708 /*- End of function --------------------------------------------------------*/ | |
| 709 | |
| 710 static int free_buffers(t4_state_t *s) | |
| 711 { | |
| 712 if (s->image_buffer) | |
| 713 { | |
| 714 free(s->image_buffer); | |
| 715 s->image_buffer = NULL; | |
| 716 s->image_buffer_size = 0; | |
| 717 } | |
| 718 if (s->cur_runs) | |
| 719 { | |
| 720 free(s->cur_runs); | |
| 721 s->cur_runs = NULL; | |
| 722 } | |
| 723 if (s->ref_runs) | |
| 724 { | |
| 725 free(s->ref_runs); | |
| 726 s->ref_runs = NULL; | |
| 727 } | |
| 728 if (s->row_buf) | |
| 729 { | |
| 730 free(s->row_buf); | |
| 731 s->row_buf = NULL; | |
| 732 } | |
| 733 return 0; | |
| 734 } | |
| 735 /*- End of function --------------------------------------------------------*/ | |
| 736 | |
| 737 static int row_to_run_lengths(uint32_t list[], const uint8_t row[], int width) | |
| 738 { | |
| 739 uint32_t flip; | |
| 740 uint32_t x; | |
| 741 int span; | |
| 742 int entry; | |
| 743 int frag; | |
| 744 int rem; | |
| 745 int limit; | |
| 746 int i; | |
| 747 int pos; | |
| 748 | |
| 749 /* Deal with whole words first. We know we are starting on a word boundary. */ | |
| 750 entry = 0; | |
| 751 flip = 0; | |
| 752 limit = (width >> 3) & ~3; | |
| 753 span = 0; | |
| 754 pos = 0; | |
| 755 for (i = 0; i < limit; i += sizeof(uint32_t)) | |
| 756 { | |
| 757 x = *((uint32_t *) &row[i]); | |
| 758 if (x != flip) | |
| 759 { | |
| 760 x = ((uint32_t) row[i] << 24) | ((uint32_t) row[i + 1] << 16) | ((uint32_t) row[i + 2] << 8) | ((uint32_t) row[i + 3]); | |
| 761 /* We know we are going to find at least one transition. */ | |
| 762 frag = 31 - top_bit(x ^ flip); | |
| 763 pos += ((i << 3) - span + frag); | |
| 764 list[entry++] = pos; | |
| 765 x <<= frag; | |
| 766 flip ^= 0xFFFFFFFF; | |
| 767 rem = 32 - frag; | |
| 768 /* Now see if there are any more */ | |
| 769 while ((frag = 31 - top_bit(x ^ flip)) < rem) | |
| 770 { | |
| 771 pos += frag; | |
| 772 list[entry++] = pos; | |
| 773 x <<= frag; | |
| 774 flip ^= 0xFFFFFFFF; | |
| 775 rem -= frag; | |
| 776 } | |
| 777 /* Save the remainder of the word */ | |
| 778 span = (i << 3) + 32 - rem; | |
| 779 } | |
| 780 } | |
| 781 /* Now deal with some whole bytes, if there are any left. */ | |
| 782 limit = width >> 3; | |
| 783 flip &= 0xFF000000; | |
| 784 if (i < limit) | |
| 785 { | |
| 786 for ( ; i < limit; i++) | |
| 787 { | |
| 788 x = (uint32_t) row[i] << 24; | |
| 789 if (x != flip) | |
| 790 { | |
| 791 /* We know we are going to find at least one transition. */ | |
| 792 frag = 31 - top_bit(x ^ flip); | |
| 793 pos += ((i << 3) - span + frag); | |
| 794 list[entry++] = pos; | |
| 795 x <<= frag; | |
| 796 flip ^= 0xFF000000; | |
| 797 rem = 8 - frag; | |
| 798 /* Now see if there are any more */ | |
| 799 while ((frag = 31 - top_bit(x ^ flip)) < rem) | |
| 800 { | |
| 801 pos += frag; | |
| 802 list[entry++] = pos; | |
| 803 x <<= frag; | |
| 804 flip ^= 0xFF000000; | |
| 805 rem -= frag; | |
| 806 } | |
| 807 /* Save the remainder of the word */ | |
| 808 span = (i << 3) + 8 - rem; | |
| 809 } | |
| 810 } | |
| 811 } | |
| 812 /* Deal with any left over fractional byte. */ | |
| 813 span = (i << 3) - span; | |
| 814 if ((rem = width & 7)) | |
| 815 { | |
| 816 x = row[i]; | |
| 817 x <<= 24; | |
| 818 do | |
| 819 { | |
| 820 frag = 31 - top_bit(x ^ flip); | |
| 821 if (frag > rem) | |
| 822 frag = rem; | |
| 823 pos += (span + frag); | |
| 824 list[entry++] = pos; | |
| 825 x <<= frag; | |
| 826 span = 0; | |
| 827 flip ^= 0xFF000000; | |
| 828 rem -= frag; | |
| 829 } | |
| 830 while (rem > 0); | |
| 831 } | |
| 832 else | |
| 833 { | |
| 834 if (span) | |
| 835 { | |
| 836 pos += span; | |
| 837 list[entry++] = pos; | |
| 838 } | |
| 839 } | |
| 840 return entry; | |
| 841 } | |
| 842 /*- End of function --------------------------------------------------------*/ | |
| 843 | |
| 844 static __inline__ int put_encoded_bits(t4_state_t *s, uint32_t bits, int length) | |
| 845 { | |
| 846 uint8_t *t; | |
| 847 | |
| 848 /* We might be called with a large length value, to spew out a mass of zero bits for | |
| 849 minimum row length padding. */ | |
| 850 s->tx_bitstream |= (bits << s->tx_bits); | |
| 851 s->tx_bits += length; | |
| 852 s->row_bits += length; | |
| 853 if ((s->image_size + (s->tx_bits + 7)/8) >= s->image_buffer_size) | |
| 854 { | |
| 855 if ((t = realloc(s->image_buffer, s->image_buffer_size + 100*s->bytes_per_row)) == NULL) | |
| 856 return -1; | |
| 857 s->image_buffer = t; | |
| 858 s->image_buffer_size += 100*s->bytes_per_row; | |
| 859 } | |
| 860 while (s->tx_bits >= 8) | |
| 861 { | |
| 862 s->image_buffer[s->image_size++] = (uint8_t) (s->tx_bitstream & 0xFF); | |
| 863 s->tx_bitstream >>= 8; | |
| 864 s->tx_bits -= 8; | |
| 865 } | |
| 866 return 0; | |
| 867 } | |
| 868 /*- End of function --------------------------------------------------------*/ | |
| 869 | |
| 870 /* | |
| 871 * Write the sequence of codes that describes | |
| 872 * the specified span of zero's or one's. The | |
| 873 * appropriate table that holds the make-up and | |
| 874 * terminating codes is supplied. | |
| 875 */ | |
| 876 static __inline__ int put_1d_span(t4_state_t *s, int32_t span, const t4_run_table_entry_t *tab) | |
| 877 { | |
| 878 const t4_run_table_entry_t *te; | |
| 879 | |
| 880 te = &tab[63 + (2560 >> 6)]; | |
| 881 while (span >= 2560 + 64) | |
| 882 { | |
| 883 if (put_encoded_bits(s, te->code, te->length)) | |
| 884 return -1; | |
| 885 span -= te->run_length; | |
| 886 } | |
| 887 te = &tab[63 + (span >> 6)]; | |
| 888 if (span >= 64) | |
| 889 { | |
| 890 if (put_encoded_bits(s, te->code, te->length)) | |
| 891 return -1; | |
| 892 span -= te->run_length; | |
| 893 } | |
| 894 if (put_encoded_bits(s, tab[span].code, tab[span].length)) | |
| 895 return -1; | |
| 896 return 0; | |
| 897 } | |
| 898 /*- End of function --------------------------------------------------------*/ | |
| 899 | |
| 900 #define pixel_is_black(x,bit) (((x)[(bit) >> 3] << ((bit) & 7)) & 0x80) | |
| 901 | |
| 902 /* | |
| 903 * Write an EOL code to the output stream. We also handle writing the tag | |
| 904 * bit for the next scanline when doing 2D encoding. | |
| 905 */ | |
| 906 static void encode_eol(t4_state_t *s) | |
| 907 { | |
| 908 uint32_t code; | |
| 909 int length; | |
| 910 | |
| 911 if (s->line_encoding == T4_COMPRESSION_ITU_T4_2D) | |
| 912 { | |
| 913 code = 0x0800 | ((!s->row_is_2d) << 12); | |
| 914 length = 13; | |
| 915 } | |
| 916 else | |
| 917 { | |
| 918 /* T.4 1D EOL, or T.6 EOFB */ | |
| 919 code = 0x800; | |
| 920 length = 12; | |
| 921 } | |
| 922 if (s->row_bits) | |
| 923 { | |
| 924 /* We may need to pad the row to a minimum length, unless we are in T.6 mode. | |
| 925 In T.6 we only come here at the end of the page to add the EOFB marker, which | |
| 926 is like two 1D EOLs. */ | |
| 927 if (s->line_encoding != T4_COMPRESSION_ITU_T6) | |
| 928 { | |
| 929 if (s->row_bits + length < s->t4_t6_tx.min_bits_per_row) | |
| 930 put_encoded_bits(s, 0, s->t4_t6_tx.min_bits_per_row - (s->row_bits + length)); | |
| 931 } | |
| 932 put_encoded_bits(s, code, length); | |
| 933 update_row_bit_info(s); | |
| 934 } | |
| 935 else | |
| 936 { | |
| 937 /* We don't pad zero length rows. They are the consecutive EOLs which end a page. */ | |
| 938 put_encoded_bits(s, code, length); | |
| 939 /* Don't do the full update row bit info, or the minimum suddenly drops to the | |
| 940 length of an EOL. Just clear the row bits, so we treat the next EOL as an | |
| 941 end of page EOL, with no padding. */ | |
| 942 s->row_bits = 0; | |
| 943 } | |
| 944 } | |
| 945 /*- End of function --------------------------------------------------------*/ | |
| 946 | |
| 947 /* | |
| 948 * 2D-encode a row of pixels. Consult ITU specification T.4 for the algorithm. | |
| 949 */ | |
| 950 static void encode_2d_row(t4_state_t *s) | |
| 951 { | |
| 952 static const t4_run_table_entry_t codes[] = | |
| 953 { | |
| 954 { 7, 0x60, 0 }, /* VR3 0000 011 */ | |
| 955 { 6, 0x30, 0 }, /* VR2 0000 11 */ | |
| 956 { 3, 0x06, 0 }, /* VR1 011 */ | |
| 957 { 1, 0x01, 0 }, /* V0 1 */ | |
| 958 { 3, 0x02, 0 }, /* VL1 010 */ | |
| 959 { 6, 0x10, 0 }, /* VL2 0000 10 */ | |
| 960 { 7, 0x20, 0 }, /* VL3 0000 010 */ | |
| 961 { 3, 0x04, 0 }, /* horizontal 001 */ | |
| 962 { 4, 0x08, 0 } /* pass 0001 */ | |
| 963 }; | |
| 964 | |
| 965 /* The reference or starting changing element on the coding line. At the start of the coding | |
| 966 line, a0 is set on an imaginary white changing element situated just before the first element | |
| 967 on the line. During the coding of the coding line, the position of a0 is defined by the | |
| 968 previous coding mode. (See T.4/4.2.1.3.2.) */ | |
| 969 int a0; | |
| 970 /* The next changing element to the right of a0 on the coding line. */ | |
| 971 int a1; | |
| 972 /* The next changing element to the right of a1 on the coding line. */ | |
| 973 int a2; | |
| 974 /* The first changing element on the reference line to the right of a0 and of opposite colour to a0. */ | |
| 975 int b1; | |
| 976 /* The next changing element to the right of b1 on the reference line. */ | |
| 977 int b2; | |
| 978 int diff; | |
| 979 int a_cursor; | |
| 980 int b_cursor; | |
| 981 int cur_steps; | |
| 982 uint32_t *p; | |
| 983 | |
| 984 /* | |
| 985 b1 b2 | |
| 986 XX XX XX XX XX -- -- -- -- -- XX XX XX -- -- -- -- -- | |
| 987 XX XX XX -- -- -- -- -- XX XX XX XX XX XX -- -- -- -- | |
| 988 a0 a1 a2 | |
| 989 | |
| 990 | |
| 991 a) Pass mode | |
| 992 This mode is identified when the position of b2 lies to the left of a1. When this mode | |
| 993 has been coded, a0 is set on the element of the coding line below b2 in preparation for | |
| 994 the next coding (i.e. on a0'). | |
| 995 | |
| 996 b1 b2 | |
| 997 XX XX XX XX -- -- XX XX XX -- -- -- -- -- | |
| 998 XX XX -- -- -- -- -- -- -- -- -- -- XX XX | |
| 999 a0 a0' a1 | |
| 1000 Pass mode | |
| 1001 | |
| 1002 | |
| 1003 However, the state where b2 occurs just above a1, as shown in the figure below, is not | |
| 1004 considered as a pass mode. | |
| 1005 | |
| 1006 b1 b2 | |
| 1007 XX XX XX XX -- -- XX XX XX -- -- -- -- -- | |
| 1008 XX XX -- -- -- -- -- -- -- XX XX XX XX XX | |
| 1009 a0 a1 | |
| 1010 Not pass mode | |
| 1011 | |
| 1012 | |
| 1013 b) Vertical mode | |
| 1014 When this mode is identified, the position of a1 is coded relative to the position of b1. | |
| 1015 The relative distance a1b1 can take on one of seven values V(0), VR(1), VR(2), VR(3), | |
| 1016 VL(1), VL(2) and VL(3), each of which is represented by a separate code word. The | |
| 1017 subscripts R and L indicate that a1 is to the right or left respectively of b1, and the | |
| 1018 number in brackets indicates the value of the distance a1b1. After vertical mode coding | |
| 1019 has occurred, the position of a0 is set on a1 (see figure below). | |
| 1020 | |
| 1021 c) Horizontal mode | |
| 1022 When this mode is identified, both the run-lengths a0a1 and a1a2 are coded using the code | |
| 1023 words H + M(a0a1) + M(a1a2). H is the flag code word 001 taken from the two-dimensional | |
| 1024 code table. M(a0a1) and M(a1a2) are code words which represent the length and "colour" | |
| 1025 of the runs a0a1 and a1a2 respectively and are taken from the appropriate white or black | |
| 1026 one-dimensional code tables. After a horizontal mode coding, the position of a0 is set on | |
| 1027 a2 (see figure below). | |
| 1028 | |
| 1029 Vertical | |
| 1030 <a1 b1> | |
| 1031 b1 b2 | |
| 1032 -- XX XX XX XX XX -- -- -- -- -- -- -- -- XX XX XX XX -- -- -- | |
| 1033 -- -- -- -- -- -- -- -- -- -- -- -- XX XX XX XX XX XX XX -- -- | |
| 1034 a0 a1 a2 | |
| 1035 <-------- a0a1 --------><-------- a1a2 ------------> | |
| 1036 Horizontal mode | |
| 1037 Vertical and horizontal modes | |
| 1038 */ | |
| 1039 /* The following implements the 2-D encoding section of the flow chart in Figure7/T.4 */ | |
| 1040 cur_steps = row_to_run_lengths(s->cur_runs, s->row_buf, s->image_width); | |
| 1041 /* Stretch the row a little, so when we step by 2 we are guaranteed to | |
| 1042 hit an entry showing the row length */ | |
| 1043 s->cur_runs[cur_steps] = | |
| 1044 s->cur_runs[cur_steps + 1] = | |
| 1045 s->cur_runs[cur_steps + 2] = s->cur_runs[cur_steps - 1]; | |
| 1046 | |
| 1047 a0 = 0; | |
| 1048 a1 = s->cur_runs[0]; | |
| 1049 b1 = s->ref_runs[0]; | |
| 1050 a_cursor = 0; | |
| 1051 b_cursor = 0; | |
| 1052 for (;;) | |
| 1053 { | |
| 1054 b2 = s->ref_runs[b_cursor + 1]; | |
| 1055 if (b2 >= a1) | |
| 1056 { | |
| 1057 diff = b1 - a1; | |
| 1058 if (abs(diff) <= 3) | |
| 1059 { | |
| 1060 /* Vertical mode coding */ | |
| 1061 put_encoded_bits(s, codes[diff + 3].code, codes[diff + 3].length); | |
| 1062 a0 = a1; | |
| 1063 a_cursor++; | |
| 1064 } | |
| 1065 else | |
| 1066 { | |
| 1067 /* Horizontal mode coding */ | |
| 1068 a2 = s->cur_runs[a_cursor + 1]; | |
| 1069 put_encoded_bits(s, codes[7].code, codes[7].length); | |
| 1070 if (a0 + a1 == 0 || pixel_is_black(s->row_buf, a0) == 0) | |
| 1071 { | |
| 1072 put_1d_span(s, a1 - a0, t4_white_codes); | |
| 1073 put_1d_span(s, a2 - a1, t4_black_codes); | |
| 1074 } | |
| 1075 else | |
| 1076 { | |
| 1077 put_1d_span(s, a1 - a0, t4_black_codes); | |
| 1078 put_1d_span(s, a2 - a1, t4_white_codes); | |
| 1079 } | |
| 1080 a0 = a2; | |
| 1081 a_cursor += 2; | |
| 1082 } | |
| 1083 if (a0 >= s->image_width) | |
| 1084 break; | |
| 1085 if (a_cursor >= cur_steps) | |
| 1086 a_cursor = cur_steps - 1; | |
| 1087 a1 = s->cur_runs[a_cursor]; | |
| 1088 } | |
| 1089 else | |
| 1090 { | |
| 1091 /* Pass mode coding */ | |
| 1092 put_encoded_bits(s, codes[8].code, codes[8].length); | |
| 1093 /* We now set a0 to somewhere in the middle of its current run, | |
| 1094 but we know are aren't moving beyond that run. */ | |
| 1095 a0 = b2; | |
| 1096 if (a0 >= s->image_width) | |
| 1097 break; | |
| 1098 } | |
| 1099 /* We need to hunt for the correct position in the reference row, as the | |
| 1100 runs there have no particular alignment with the runs in the current | |
| 1101 row. */ | |
| 1102 if (pixel_is_black(s->row_buf, a0)) | |
| 1103 b_cursor |= 1; | |
| 1104 else | |
| 1105 b_cursor &= ~1; | |
| 1106 if (a0 < (int) s->ref_runs[b_cursor]) | |
| 1107 { | |
| 1108 for ( ; b_cursor >= 0; b_cursor -= 2) | |
| 1109 { | |
| 1110 if (a0 >= (int) s->ref_runs[b_cursor]) | |
| 1111 break; | |
| 1112 } | |
| 1113 b_cursor += 2; | |
| 1114 } | |
| 1115 else | |
| 1116 { | |
| 1117 for ( ; b_cursor < s->t4_t6_tx.ref_steps; b_cursor += 2) | |
| 1118 { | |
| 1119 if (a0 < (int) s->ref_runs[b_cursor]) | |
| 1120 break; | |
| 1121 } | |
| 1122 if (b_cursor >= s->t4_t6_tx.ref_steps) | |
| 1123 b_cursor = s->t4_t6_tx.ref_steps - 1; | |
| 1124 } | |
| 1125 b1 = s->ref_runs[b_cursor]; | |
| 1126 } | |
| 1127 /* Swap the buffers */ | |
| 1128 s->t4_t6_tx.ref_steps = cur_steps; | |
| 1129 p = s->cur_runs; | |
| 1130 s->cur_runs = s->ref_runs; | |
| 1131 s->ref_runs = p; | |
| 1132 } | |
| 1133 /*- End of function --------------------------------------------------------*/ | |
| 1134 | |
| 1135 /* | |
| 1136 * 1D-encode a row of pixels. The encoding is a sequence of all-white or | |
| 1137 * all-black spans of pixels encoded with Huffman codes. | |
| 1138 */ | |
| 1139 static void encode_1d_row(t4_state_t *s) | |
| 1140 { | |
| 1141 int i; | |
| 1142 | |
| 1143 /* Do our work in the reference row buffer, and it is already in place if | |
| 1144 we need a reference row for a following 2D encoded row. */ | |
| 1145 s->t4_t6_tx.ref_steps = row_to_run_lengths(s->ref_runs, s->row_buf, s->image_width); | |
| 1146 put_1d_span(s, s->ref_runs[0], t4_white_codes); | |
| 1147 for (i = 1; i < s->t4_t6_tx.ref_steps; i++) | |
| 1148 put_1d_span(s, s->ref_runs[i] - s->ref_runs[i - 1], (i & 1) ? t4_black_codes : t4_white_codes); | |
| 1149 /* Stretch the row a little, so when we step by 2 we are guaranteed to | |
| 1150 hit an entry showing the row length */ | |
| 1151 s->ref_runs[s->t4_t6_tx.ref_steps] = | |
| 1152 s->ref_runs[s->t4_t6_tx.ref_steps + 1] = | |
| 1153 s->ref_runs[s->t4_t6_tx.ref_steps + 2] = s->ref_runs[s->t4_t6_tx.ref_steps - 1]; | |
| 1154 } | |
| 1155 /*- End of function --------------------------------------------------------*/ | |
| 1156 | |
| 1157 static int encode_row(t4_state_t *s) | |
| 1158 { | |
| 1159 switch (s->line_encoding) | |
| 1160 { | |
| 1161 case T4_COMPRESSION_ITU_T6: | |
| 1162 /* T.6 compression is a trivial step up from T.4 2D, so we just | |
| 1163 throw it in here. T.6 is only used with error correction, | |
| 1164 so it does not need independantly compressed (i.e. 1D) lines | |
| 1165 to recover from data errors. It doesn't need EOLs, either. */ | |
| 1166 if (s->row_bits) | |
| 1167 update_row_bit_info(s); | |
| 1168 encode_2d_row(s); | |
| 1169 break; | |
| 1170 case T4_COMPRESSION_ITU_T4_2D: | |
| 1171 encode_eol(s); | |
| 1172 if (s->row_is_2d) | |
| 1173 { | |
| 1174 encode_2d_row(s); | |
| 1175 s->t4_t6_tx.rows_to_next_1d_row--; | |
| 1176 } | |
| 1177 else | |
| 1178 { | |
| 1179 encode_1d_row(s); | |
| 1180 s->row_is_2d = TRUE; | |
| 1181 } | |
| 1182 if (s->t4_t6_tx.rows_to_next_1d_row <= 0) | |
| 1183 { | |
| 1184 /* Insert a row of 1D encoding */ | |
| 1185 s->row_is_2d = FALSE; | |
| 1186 s->t4_t6_tx.rows_to_next_1d_row = s->t4_t6_tx.max_rows_to_next_1d_row - 1; | |
| 1187 } | |
| 1188 break; | |
| 1189 default: | |
| 1190 case T4_COMPRESSION_ITU_T4_1D: | |
| 1191 encode_eol(s); | |
| 1192 encode_1d_row(s); | |
| 1193 break; | |
| 1194 } | |
| 1195 s->row++; | |
| 1196 return 0; | |
| 1197 } | |
| 1198 /*- End of function --------------------------------------------------------*/ | |
| 1199 | |
| 1200 SPAN_DECLARE(int) t4_tx_set_row_read_handler(t4_state_t *s, t4_row_read_handler_t handler, void *user_data) | |
| 1201 { | |
| 1202 s->t4_t6_tx.row_read_handler = handler; | |
| 1203 s->t4_t6_tx.row_read_user_data = user_data; | |
| 1204 return 0; | |
| 1205 } | |
| 1206 /*- End of function --------------------------------------------------------*/ | |
| 1207 | |
| 1208 SPAN_DECLARE(t4_state_t *) t4_tx_init(t4_state_t *s, const char *file, int start_page, int stop_page) | |
| 1209 { | |
| 1210 int run_space; | |
| 1211 | |
| 1212 if (s == NULL) | |
| 1213 { | |
| 1214 if ((s = (t4_state_t *) malloc(sizeof(*s))) == NULL) | |
| 1215 return NULL; | |
| 1216 } | |
| 1217 memset(s, 0, sizeof(*s)); | |
| 1218 span_log_init(&s->logging, SPAN_LOG_NONE, NULL); | |
| 1219 span_log_set_protocol(&s->logging, "T.4"); | |
| 1220 s->rx = FALSE; | |
| 1221 | |
| 1222 span_log(&s->logging, SPAN_LOG_FLOW, "Start tx document\n"); | |
| 1223 | |
| 1224 if (open_tiff_input_file(s, file) < 0) | |
| 1225 return NULL; | |
| 1226 s->tiff.file = strdup(file); | |
| 1227 s->current_page = | |
| 1228 s->tiff.start_page = (start_page >= 0) ? start_page : 0; | |
| 1229 s->tiff.stop_page = (stop_page >= 0) ? stop_page : INT_MAX; | |
| 1230 | |
| 1231 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page)) | |
| 1232 return NULL; | |
| 1233 if (get_tiff_directory_info(s)) | |
| 1234 { | |
| 1235 close_tiff_input_file(s); | |
| 1236 return NULL; | |
| 1237 } | |
| 1238 | |
| 1239 s->t4_t6_tx.rows_to_next_1d_row = s->t4_t6_tx.max_rows_to_next_1d_row - 1; | |
| 1240 | |
| 1241 s->tiff.pages_in_file = -1; | |
| 1242 | |
| 1243 run_space = (s->image_width + 4)*sizeof(uint32_t); | |
| 1244 if ((s->cur_runs = (uint32_t *) malloc(run_space)) == NULL) | |
| 1245 return NULL; | |
| 1246 if ((s->ref_runs = (uint32_t *) malloc(run_space)) == NULL) | |
| 1247 { | |
| 1248 free_buffers(s); | |
| 1249 close_tiff_input_file(s); | |
| 1250 return NULL; | |
| 1251 } | |
| 1252 if ((s->row_buf = malloc(s->bytes_per_row)) == NULL) | |
| 1253 { | |
| 1254 free_buffers(s); | |
| 1255 close_tiff_input_file(s); | |
| 1256 return NULL; | |
| 1257 } | |
| 1258 s->ref_runs[0] = | |
| 1259 s->ref_runs[1] = | |
| 1260 s->ref_runs[2] = | |
| 1261 s->ref_runs[3] = s->image_width; | |
| 1262 s->t4_t6_tx.ref_steps = 1; | |
| 1263 s->image_buffer_size = 0; | |
| 1264 return s; | |
| 1265 } | |
| 1266 /*- End of function --------------------------------------------------------*/ | |
| 1267 | |
| 1268 SPAN_DECLARE(int) t4_tx_start_page(t4_state_t *s) | |
| 1269 { | |
| 1270 int row; | |
| 1271 int i; | |
| 1272 int run_space; | |
| 1273 int len; | |
| 1274 int old_image_width; | |
| 1275 uint8_t *bufptr8; | |
| 1276 uint32_t *bufptr; | |
| 1277 | |
| 1278 span_log(&s->logging, SPAN_LOG_FLOW, "Start tx page %d\n", s->current_page); | |
| 1279 if (s->current_page > s->tiff.stop_page) | |
| 1280 return -1; | |
| 1281 if (s->tiff.tiff_file == NULL) | |
| 1282 return -1; | |
| 1283 old_image_width = s->image_width; | |
| 1284 if (s->t4_t6_tx.row_read_handler == NULL) | |
| 1285 { | |
| 1286 #if defined(HAVE_LIBTIFF) | |
| 1287 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page)) | |
| 1288 return -1; | |
| 1289 get_tiff_directory_info(s); | |
| 1290 #endif | |
| 1291 } | |
| 1292 s->image_size = 0; | |
| 1293 s->tx_bitstream = 0; | |
| 1294 s->tx_bits = 0; | |
| 1295 s->row_is_2d = (s->line_encoding == T4_COMPRESSION_ITU_T6); | |
| 1296 s->t4_t6_tx.rows_to_next_1d_row = s->t4_t6_tx.max_rows_to_next_1d_row - 1; | |
| 1297 | |
| 1298 /* Allow for pages being of different width. */ | |
| 1299 run_space = (s->image_width + 4)*sizeof(uint32_t); | |
| 1300 if (old_image_width != s->image_width) | |
| 1301 { | |
| 1302 s->bytes_per_row = (s->image_width + 7)/8; | |
| 1303 | |
| 1304 if ((bufptr = (uint32_t *) realloc(s->cur_runs, run_space)) == NULL) | |
| 1305 return -1; | |
| 1306 s->cur_runs = bufptr; | |
| 1307 if ((bufptr = (uint32_t *) realloc(s->ref_runs, run_space)) == NULL) | |
| 1308 return -1; | |
| 1309 s->ref_runs = bufptr; | |
| 1310 if ((bufptr8 = realloc(s->row_buf, s->bytes_per_row)) == NULL) | |
| 1311 return -1; | |
| 1312 s->row_buf = bufptr8; | |
| 1313 } | |
| 1314 s->ref_runs[0] = | |
| 1315 s->ref_runs[1] = | |
| 1316 s->ref_runs[2] = | |
| 1317 s->ref_runs[3] = s->image_width; | |
| 1318 s->t4_t6_tx.ref_steps = 1; | |
| 1319 | |
| 1320 s->row_bits = 0; | |
| 1321 s->min_row_bits = INT_MAX; | |
| 1322 s->max_row_bits = 0; | |
| 1323 | |
| 1324 if (s->t4_t6_tx.header_info && s->t4_t6_tx.header_info[0]) | |
| 1325 { | |
| 1326 if (t4_tx_put_fax_header(s)) | |
| 1327 return -1; | |
| 1328 } | |
| 1329 if (s->t4_t6_tx.row_read_handler) | |
| 1330 { | |
| 1331 for (row = 0; ; row++) | |
| 1332 { | |
| 1333 if ((len = s->t4_t6_tx.row_read_handler(s->t4_t6_tx.row_read_user_data, s->row_buf, s->bytes_per_row)) < 0) | |
| 1334 { | |
| 1335 span_log(&s->logging, SPAN_LOG_WARNING, "%s: Read error at row %d.\n", s->tiff.file, row); | |
| 1336 break; | |
| 1337 } | |
| 1338 if (len == 0) | |
| 1339 break; | |
| 1340 if (encode_row(s)) | |
| 1341 return -1; | |
| 1342 } | |
| 1343 s->image_length = row; | |
| 1344 } | |
| 1345 else | |
| 1346 { | |
| 1347 if ((s->image_length = read_tiff_image(s)) < 0) | |
| 1348 return -1; | |
| 1349 } | |
| 1350 if (s->line_encoding == T4_COMPRESSION_ITU_T6) | |
| 1351 { | |
| 1352 /* Attach an EOFB (end of facsimile block == 2 x EOLs) to the end of the page */ | |
| 1353 for (i = 0; i < EOLS_TO_END_T6_TX_PAGE; i++) | |
| 1354 encode_eol(s); | |
| 1355 } | |
| 1356 else | |
| 1357 { | |
| 1358 /* Attach an RTC (return to control == 6 x EOLs) to the end of the page */ | |
| 1359 s->row_is_2d = FALSE; | |
| 1360 for (i = 0; i < EOLS_TO_END_T4_TX_PAGE; i++) | |
| 1361 encode_eol(s); | |
| 1362 } | |
| 1363 | |
| 1364 /* Force any partial byte in progress to flush using ones. Any post EOL padding when | |
| 1365 sending is normally ones, so this is consistent. */ | |
| 1366 put_encoded_bits(s, 0xFF, 7); | |
| 1367 s->t4_t6_tx.bit_pos = 7; | |
| 1368 s->t4_t6_tx.bit_ptr = 0; | |
| 1369 s->line_image_size = s->image_size*8; | |
| 1370 | |
| 1371 return 0; | |
| 1372 } | |
| 1373 /*- End of function --------------------------------------------------------*/ | |
| 1374 | |
| 1375 SPAN_DECLARE(int) t4_tx_next_page_has_different_format(t4_state_t *s) | |
| 1376 { | |
| 1377 span_log(&s->logging, SPAN_LOG_FLOW, "Checking for the existance of page %d\n", s->current_page + 1); | |
| 1378 if (s->current_page >= s->tiff.stop_page) | |
| 1379 return -1; | |
| 1380 if (s->t4_t6_tx.row_read_handler == NULL) | |
| 1381 { | |
| 1382 #if defined(HAVE_LIBTIFF) | |
| 1383 if (s->tiff.tiff_file == NULL) | |
| 1384 return -1; | |
| 1385 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page + 1)) | |
| 1386 return -1; | |
| 1387 return test_tiff_directory_info(s); | |
| 1388 #endif | |
| 1389 } | |
| 1390 return 0; | |
| 1391 } | |
| 1392 /*- End of function --------------------------------------------------------*/ | |
| 1393 | |
| 1394 SPAN_DECLARE(int) t4_tx_restart_page(t4_state_t *s) | |
| 1395 { | |
| 1396 s->t4_t6_tx.bit_pos = 7; | |
| 1397 s->t4_t6_tx.bit_ptr = 0; | |
| 1398 return 0; | |
| 1399 } | |
| 1400 /*- End of function --------------------------------------------------------*/ | |
| 1401 | |
| 1402 SPAN_DECLARE(int) t4_tx_end_page(t4_state_t *s) | |
| 1403 { | |
| 1404 s->current_page++; | |
| 1405 return 0; | |
| 1406 } | |
| 1407 /*- End of function --------------------------------------------------------*/ | |
| 1408 | |
| 1409 SPAN_DECLARE(int) t4_tx_get_bit(t4_state_t *s) | |
| 1410 { | |
| 1411 int bit; | |
| 1412 | |
| 1413 if (s->t4_t6_tx.bit_ptr >= s->image_size) | |
| 1414 return SIG_STATUS_END_OF_DATA; | |
| 1415 bit = (s->image_buffer[s->t4_t6_tx.bit_ptr] >> (7 - s->t4_t6_tx.bit_pos)) & 1; | |
| 1416 if (--s->t4_t6_tx.bit_pos < 0) | |
| 1417 { | |
| 1418 s->t4_t6_tx.bit_pos = 7; | |
| 1419 s->t4_t6_tx.bit_ptr++; | |
| 1420 } | |
| 1421 return bit; | |
| 1422 } | |
| 1423 /*- End of function --------------------------------------------------------*/ | |
| 1424 | |
| 1425 SPAN_DECLARE(int) t4_tx_get_byte(t4_state_t *s) | |
| 1426 { | |
| 1427 if (s->t4_t6_tx.bit_ptr >= s->image_size) | |
| 1428 return 0x100; | |
| 1429 return s->image_buffer[s->t4_t6_tx.bit_ptr++]; | |
| 1430 } | |
| 1431 /*- End of function --------------------------------------------------------*/ | |
| 1432 | |
| 1433 SPAN_DECLARE(int) t4_tx_get_chunk(t4_state_t *s, uint8_t buf[], int max_len) | |
| 1434 { | |
| 1435 if (s->t4_t6_tx.bit_ptr >= s->image_size) | |
| 1436 return 0; | |
| 1437 if (s->t4_t6_tx.bit_ptr + max_len > s->image_size) | |
| 1438 max_len = s->image_size - s->t4_t6_tx.bit_ptr; | |
| 1439 memcpy(buf, &s->image_buffer[s->t4_t6_tx.bit_ptr], max_len); | |
| 1440 s->t4_t6_tx.bit_ptr += max_len; | |
| 1441 return max_len; | |
| 1442 } | |
| 1443 /*- End of function --------------------------------------------------------*/ | |
| 1444 | |
| 1445 SPAN_DECLARE(int) t4_tx_check_bit(t4_state_t *s) | |
| 1446 { | |
| 1447 int bit; | |
| 1448 | |
| 1449 if (s->t4_t6_tx.bit_ptr >= s->image_size) | |
| 1450 return SIG_STATUS_END_OF_DATA; | |
| 1451 bit = (s->image_buffer[s->t4_t6_tx.bit_ptr] >> s->t4_t6_tx.bit_pos) & 1; | |
| 1452 return bit; | |
| 1453 } | |
| 1454 /*- End of function --------------------------------------------------------*/ | |
| 1455 | |
| 1456 SPAN_DECLARE(int) t4_tx_release(t4_state_t *s) | |
| 1457 { | |
| 1458 if (s->rx) | |
| 1459 return -1; | |
| 1460 if (s->tiff.tiff_file) | |
| 1461 close_tiff_input_file(s); | |
| 1462 free_buffers(s); | |
| 1463 return 0; | |
| 1464 } | |
| 1465 /*- End of function --------------------------------------------------------*/ | |
| 1466 | |
| 1467 SPAN_DECLARE(int) t4_tx_free(t4_state_t *s) | |
| 1468 { | |
| 1469 int ret; | |
| 1470 | |
| 1471 ret = t4_tx_release(s); | |
| 1472 free(s); | |
| 1473 return ret; | |
| 1474 } | |
| 1475 /*- End of function --------------------------------------------------------*/ | |
| 1476 | |
| 1477 SPAN_DECLARE(void) t4_tx_set_tx_encoding(t4_state_t *s, int encoding) | |
| 1478 { | |
| 1479 s->line_encoding = encoding; | |
| 1480 s->t4_t6_tx.rows_to_next_1d_row = s->t4_t6_tx.max_rows_to_next_1d_row - 1; | |
| 1481 s->row_is_2d = FALSE; | |
| 1482 } | |
| 1483 /*- End of function --------------------------------------------------------*/ | |
| 1484 | |
| 1485 SPAN_DECLARE(void) t4_tx_set_min_row_bits(t4_state_t *s, int bits) | |
| 1486 { | |
| 1487 s->t4_t6_tx.min_bits_per_row = bits; | |
| 1488 } | |
| 1489 /*- End of function --------------------------------------------------------*/ | |
| 1490 | |
| 1491 SPAN_DECLARE(void) t4_tx_set_local_ident(t4_state_t *s, const char *ident) | |
| 1492 { | |
| 1493 s->tiff.local_ident = (ident && ident[0]) ? ident : NULL; | |
| 1494 } | |
| 1495 /*- End of function --------------------------------------------------------*/ | |
| 1496 | |
| 1497 SPAN_DECLARE(void) t4_tx_set_header_info(t4_state_t *s, const char *info) | |
| 1498 { | |
| 1499 s->t4_t6_tx.header_info = (info && info[0]) ? info : NULL; | |
| 1500 } | |
| 1501 /*- End of function --------------------------------------------------------*/ | |
| 1502 | |
| 1503 SPAN_DECLARE(int) t4_tx_get_y_resolution(t4_state_t *s) | |
| 1504 { | |
| 1505 return s->y_resolution; | |
| 1506 } | |
| 1507 /*- End of function --------------------------------------------------------*/ | |
| 1508 | |
| 1509 SPAN_DECLARE(int) t4_tx_get_x_resolution(t4_state_t *s) | |
| 1510 { | |
| 1511 return s->x_resolution; | |
| 1512 } | |
| 1513 /*- End of function --------------------------------------------------------*/ | |
| 1514 | |
| 1515 SPAN_DECLARE(int) t4_tx_get_image_width(t4_state_t *s) | |
| 1516 { | |
| 1517 return s->image_width; | |
| 1518 } | |
| 1519 /*- End of function --------------------------------------------------------*/ | |
| 1520 | |
| 1521 SPAN_DECLARE(int) t4_tx_get_pages_in_file(t4_state_t *s) | |
| 1522 { | |
| 1523 int max; | |
| 1524 | |
| 1525 max = 0; | |
| 1526 if (s->t4_t6_tx.row_read_handler == NULL) | |
| 1527 max = get_tiff_total_pages(s); | |
| 1528 if (max >= 0) | |
| 1529 s->tiff.pages_in_file = max; | |
| 1530 return max; | |
| 1531 } | |
| 1532 /*- End of function --------------------------------------------------------*/ | |
| 1533 | |
| 1534 SPAN_DECLARE(int) t4_tx_get_current_page_in_file(t4_state_t *s) | |
| 1535 { | |
| 1536 return s->current_page; | |
| 1537 } | |
| 1538 /*- End of function --------------------------------------------------------*/ | |
| 1539 /*- End of file ------------------------------------------------------------*/ |
