1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * t4_tx.c - ITU T.4 FAX image transmit processing
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2003, 2007, 2010 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /*! \file */
27
28 #if defined(HAVE_CONFIG_H)
29 #include "config.h"
30 #endif
31
32 #include <inttypes.h>
33 #include <stdlib.h>
34 #include <limits.h>
35 #include <stdio.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <time.h>
39 #include <memory.h>
40 #include <string.h>
41 #if defined(HAVE_TGMATH_H)
42 #include <tgmath.h>
43 #endif
44 #if defined(HAVE_MATH_H)
45 #include <math.h>
46 #endif
47 #if defined(HAVE_STDBOOL_H)
48 #include <stdbool.h>
49 #else
50 #include "spandsp/stdbool.h"
51 #endif
52 #include "floating_fudge.h"
53 #include <tiffio.h>
54
55 #include "spandsp/telephony.h"
56 #include "spandsp/alloc.h"
57 #include "spandsp/logging.h"
58 #include "spandsp/bit_operations.h"
59 #include "spandsp/async.h"
60 #include "spandsp/timezone.h"
61 #include "spandsp/t4_rx.h"
62 #include "spandsp/t4_tx.h"
63 #include "spandsp/image_translate.h"
64 #include "spandsp/t81_t82_arith_coding.h"
65 #include "spandsp/t85.h"
66 #include "spandsp/t42.h"
67 #include "spandsp/t43.h"
68 #include "spandsp/t4_t6_decode.h"
69 #include "spandsp/t4_t6_encode.h"
70
71 #include "spandsp/private/logging.h"
72 #include "spandsp/private/t81_t82_arith_coding.h"
73 #include "spandsp/private/t85.h"
74 #include "spandsp/private/t42.h"
75 #include "spandsp/private/t43.h"
76 #include "spandsp/private/t4_t6_decode.h"
77 #include "spandsp/private/t4_t6_encode.h"
78 #include "spandsp/private/image_translate.h"
79 #include "spandsp/private/t4_rx.h"
80 #include "spandsp/private/t4_tx.h"
81
82 #include "faxfont.h"
83
84 #if defined(SPANDSP_SUPPORT_TIFF_FX) && defined(HAVE_TIF_DIR_H)
85 #include <tif_dir.h>
86 #endif
87
88 /*! The number of centimetres in one inch */
89 #define CM_PER_INCH 2.54f
90
91 typedef struct
92 {
93 uint8_t *buf;
94 int ptr;
95 int row;
96 int size;
97 int bit_mask;
98 } packer_t;
99
100 static void t4_tx_set_image_type(t4_tx_state_t *s, int image_type);
101 static void set_image_width(t4_tx_state_t *s, uint32_t image_width);
102 static void set_image_length(t4_tx_state_t *s, uint32_t image_length);
103
104 static const float x_res_table[] =
105 {
106 100.0f*100.0f/CM_PER_INCH,
107 102.0f*100.0f/CM_PER_INCH,
108 200.0f*100.0f/CM_PER_INCH,
109 204.0f*100.0f/CM_PER_INCH,
110 300.0f*100.0f/CM_PER_INCH,
111 400.0f*100.0f/CM_PER_INCH,
112 408.0f*100.0f/CM_PER_INCH,
113 600.0f*100.0f/CM_PER_INCH,
114 1200.0f*100.0f/CM_PER_INCH,
115 -1.00f
116 };
117
118 static const float y_res_table[] =
119 {
120 38.50f*100.0f,
121 100.0f*100.0f/CM_PER_INCH,
122 77.00f*100.0f,
123 200.0f*100.0f/CM_PER_INCH,
124 300.0f*100.0f/CM_PER_INCH,
125 154.00f*100.0f,
126 400.0f*100.0f/CM_PER_INCH,
127 600.0f*100.0f/CM_PER_INCH,
128 800.0f*100.0f/CM_PER_INCH,
129 1200.0f*100.0f/CM_PER_INCH,
130 -1.00f
131 };
132
133 static const int resolution_map[10][9] =
134 {
135 /* x = 100 102 200 204 300 400 408 600 1200 */
136 { 0, 0, 0, T4_RESOLUTION_R8_STANDARD, 0, 0, 0, 0, 0}, /* y = 3.85/mm */
137 {T4_RESOLUTION_100_100, 0, T4_RESOLUTION_200_100, 0, 0, 0, 0, 0, 0}, /* y = 100 */
138 { 0, 0, 0, T4_RESOLUTION_R8_FINE, 0, 0, 0, 0, 0}, /* y = 7.7/mm */
139 { 0, 0, T4_RESOLUTION_200_200, 0, 0, 0, 0, 0, 0}, /* y = 200 */
140 { 0, 0, 0, 0, T4_RESOLUTION_300_300, 0, 0, 0, 0}, /* y = 300 */
141 { 0, 0, 0, T4_RESOLUTION_R8_SUPERFINE, 0, 0, T4_RESOLUTION_R16_SUPERFINE, 0, 0}, /* y = 154/mm */
142 { 0, 0, T4_RESOLUTION_200_400, 0, 0, T4_RESOLUTION_400_400, 0, 0, 0}, /* y = 400 */
143 { 0, 0, 0, 0, T4_RESOLUTION_300_600, 0, 0, T4_RESOLUTION_600_600, 0}, /* y = 600 */
144 { 0, 0, 0, 0, 0, T4_RESOLUTION_400_800, 0, 0, 0}, /* y = 800 */
145 { 0, 0, 0, 0, 0, 0, 0, T4_RESOLUTION_600_1200, T4_RESOLUTION_1200_1200} /* y = 1200 */
146 };
147
148 #if defined(SPANDSP_SUPPORT_TIFF_FX)
149 /* TIFF-FX related extensions to the tag set supported by libtiff */
150
151 static const TIFFFieldInfo tiff_fx_tiff_field_info[] =
152 {
153 {TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, FIELD_CUSTOM, false, false, (char *) "Indexed"},
154 {TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_IFD8, FIELD_CUSTOM, false, false, (char *) "GlobalParametersIFD"},
155 {TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, FIELD_CUSTOM, false, false, (char *) "ProfileType"},
156 {TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, FIELD_CUSTOM, false, false, (char *) "FaxProfile"},
157 {TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, FIELD_CUSTOM, false, false, (char *) "CodingMethods"},
158 {TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, FIELD_CUSTOM, false, false, (char *) "VersionYear"},
159 {TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, FIELD_CUSTOM, false, false, (char *) "ModeNumber"},
160 {TIFFTAG_DECODE, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SRATIONAL, FIELD_CUSTOM, false, true, (char *) "Decode"},
161 {TIFFTAG_IMAGEBASECOLOR, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SHORT, FIELD_CUSTOM, false, true, (char *) "ImageBaseColor"},
162 {TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, FIELD_CUSTOM, false, false, (char *) "T82Options"},
163 {TIFFTAG_STRIPROWCOUNTS, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_LONG, FIELD_CUSTOM, false, true, (char *) "StripRowCounts"},
164 {TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, FIELD_CUSTOM, false, false, (char *) "ImageLayer"},
165 };
166
167 #if TIFFLIB_VERSION >= 20120922 && defined(HAVE_TIF_DIR_H)
168 static TIFFField tiff_fx_tiff_fields[] =
169 {
170 { TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "Indexed" },
171 { TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, (char *) "GlobalParametersIFD", NULL },
172 { TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "ProfileType", NULL },
173 { TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "FaxProfile", NULL },
174 { TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "CodingMethods", NULL },
175 { TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "VersionYear", NULL },
176 { TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "ModeNumber", NULL },
177 { TIFFTAG_DECODE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, (char *) "Decode", NULL },
178 { TIFFTAG_IMAGEBASECOLOR, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, (char *) "ImageBaseColor", NULL },
179 { TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "T82Options", NULL },
180 { TIFFTAG_STRIPROWCOUNTS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, (char *) "StripRowCounts", NULL },
181 { TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "ImageLayer", NULL },
182 };
183
184 TIFFFieldArray tiff_fx_field_array = { tfiatOther, 0, 12, tiff_fx_tiff_fields };
185 #endif
186
187 static TIFFExtendProc _ParentExtender = NULL;
188
TIFFFXDefaultDirectory(TIFF * tif)189 static void TIFFFXDefaultDirectory(TIFF *tif)
190 {
191 /* Install the extended tag field info */
192 TIFFMergeFieldInfo(tif, tiff_fx_tiff_field_info, 12);
193
194 /* Since we may have overriddden another directory method, we call it now to
195 allow it to set up the rest of its own methods. */
196 if (_ParentExtender)
197 (*_ParentExtender)(tif);
198 }
199 /*- End of function --------------------------------------------------------*/
200
TIFF_FX_init(void)201 SPAN_DECLARE(void) TIFF_FX_init(void)
202 {
203 static int first_time = true;
204
205 if (!first_time)
206 return;
207 first_time = false;
208
209 /* Grab the inherited method and install */
210 _ParentExtender = TIFFSetTagExtender(TIFFFXDefaultDirectory);
211 }
212 /*- End of function --------------------------------------------------------*/
213 #endif
214
code_to_x_resolution(int code)215 static int code_to_x_resolution(int code)
216 {
217 static const int xxx[] =
218 {
219 T4_X_RESOLUTION_R8, /* R8 x standard */
220 T4_X_RESOLUTION_R8, /* R8 x fine */
221 T4_X_RESOLUTION_R8, /* R8 x superfine */
222 T4_X_RESOLUTION_R16, /* R16 x superfine */
223 T4_X_RESOLUTION_100, /* 100x100 */
224 T4_X_RESOLUTION_200, /* 200x100 */
225 T4_X_RESOLUTION_200, /* 200x200 */
226 T4_X_RESOLUTION_200, /* 200x400 */
227 T4_X_RESOLUTION_300, /* 300x300 */
228 T4_X_RESOLUTION_300, /* 300x600 */
229 T4_X_RESOLUTION_400, /* 400x400 */
230 T4_X_RESOLUTION_400, /* 400x800 */
231 T4_X_RESOLUTION_600, /* 600x600 */
232 T4_X_RESOLUTION_600, /* 600x1200 */
233 T4_X_RESOLUTION_1200 /* 1200x1200 */
234 };
235 int entry;
236
237 entry = top_bit(code);
238 if (entry < 0 || entry > 14)
239 return 0;
240 return xxx[entry];
241 }
242 /*- End of function --------------------------------------------------------*/
243
code_to_y_resolution(int code)244 static int code_to_y_resolution(int code)
245 {
246 static const int yyy[] =
247 {
248 T4_Y_RESOLUTION_STANDARD, /* R8 x standard */
249 T4_Y_RESOLUTION_FINE, /* R8 x fine */
250 T4_Y_RESOLUTION_SUPERFINE, /* R8 x superfine */
251 T4_Y_RESOLUTION_SUPERFINE, /* R16 x superfine */
252 T4_Y_RESOLUTION_100, /* 100x100 */
253 T4_Y_RESOLUTION_100, /* 200x100 */
254 T4_Y_RESOLUTION_200, /* 200x200 */
255 T4_Y_RESOLUTION_400, /* 200x400 */
256 T4_Y_RESOLUTION_300, /* 300x300 */
257 T4_Y_RESOLUTION_600, /* 300x600 */
258 T4_Y_RESOLUTION_400, /* 400x400 */
259 T4_Y_RESOLUTION_800, /* 400x800 */
260 T4_Y_RESOLUTION_600, /* 600x600 */
261 T4_Y_RESOLUTION_1200, /* 600x1200 */
262 T4_Y_RESOLUTION_1200 /* 1200x1200 */
263 };
264 int entry;
265
266 entry = top_bit(code);
267 if (entry < 0 || entry > 14)
268 return 0;
269 return yyy[entry];
270 }
271 /*- End of function --------------------------------------------------------*/
272
match_resolution(float actual,const float table[])273 static int match_resolution(float actual, const float table[])
274 {
275 int i;
276 int best_entry;
277 float best_ratio;
278 float ratio;
279
280 if (actual == 0.0f)
281 return -1;
282
283 best_ratio = 0.0f;
284 best_entry = -1;
285 for (i = 0; table[i] > 0.0f; i++)
286 {
287 if (actual > table[i])
288 ratio = table[i]/actual;
289 else
290 ratio = actual/table[i];
291 if (ratio > best_ratio)
292 {
293 best_entry = i;
294 best_ratio = ratio;
295 }
296 }
297 if (best_ratio < 0.95f)
298 return -1;
299 return best_entry;
300 }
301 /*- End of function --------------------------------------------------------*/
302
303 #if 0
304 static int best_colour_resolution(float actual, int allowed_resolutions)
305 {
306 static const struct
307 {
308 float resolution;
309 int resolution_code;
310 } x_res_table[] =
311 {
312 { 100.0f*100.0f/CM_PER_INCH, T4_RESOLUTION_100_100},
313 { 200.0f*100.0f/CM_PER_INCH, T4_RESOLUTION_200_200},
314 { 300.0f*100.0f/CM_PER_INCH, T4_RESOLUTION_300_300},
315 { 400.0f*100.0f/CM_PER_INCH, T4_RESOLUTION_400_400},
316 { 600.0f*100.0f/CM_PER_INCH, T4_RESOLUTION_600_600},
317 {1200.0f*100.0f/CM_PER_INCH, T4_RESOLUTION_1200_1200},
318 { -1.00f, -1}
319 };
320 int i;
321 int best_entry;
322 float best_ratio;
323 float ratio;
324
325 if (actual == 0.0f)
326 return -1;
327
328 best_ratio = 0.0f;
329 best_entry = 0;
330 for (i = 0; x_res_table[i].resolution > 0.0f; i++)
331 {
332 if (!(allowed_resolutions & x_res_table[i].resolution_code))
333 continue;
334 if (actual > x_res_table[i].resolution)
335 ratio = x_res_table[i].resolution/actual;
336 else
337 ratio = actual/x_res_table[i].resolution;
338 if (ratio > best_ratio)
339 {
340 best_entry = i;
341 best_ratio = ratio;
342 }
343 }
344 return x_res_table[best_entry].resolution_code;
345 }
346 /*- End of function --------------------------------------------------------*/
347 #endif
348
349 #if defined(SPANDSP_SUPPORT_TIFF_FX)
read_colour_map(t4_tx_state_t * s,int bits_per_sample)350 static int read_colour_map(t4_tx_state_t *s, int bits_per_sample)
351 {
352 int i;
353 uint16_t *map_L;
354 uint16_t *map_a;
355 uint16_t *map_b;
356 uint16_t *map_z;
357
358 map_L = NULL;
359 map_a = NULL;
360 map_b = NULL;
361 map_z = NULL;
362 if (!TIFFGetField(s->tiff.tiff_file, TIFFTAG_COLORMAP, &map_L, &map_a, &map_b, &map_z))
363 return -1;
364
365 /* TODO: This only allows for 8 bit deep maps */
366 span_log(&s->logging, SPAN_LOG_FLOW, "Got a colour map\n");
367 s->colour_map_entries = 1 << bits_per_sample;
368 if ((s->colour_map = span_realloc(s->colour_map, 3*s->colour_map_entries)) == NULL)
369 return -1;
370 #if 0
371 /* Sweep the colormap in the proper order */
372 for (i = 0; i < s->colour_map_entries; i++)
373 {
374 s->colour_map[3*i + 0] = (map_L[i] >> 8) & 0xFF;
375 s->colour_map[3*i + 1] = (map_a[i] >> 8) & 0xFF;
376 s->colour_map[3*i + 2] = (map_b[i] >> 8) & 0xFF;
377 span_log(&s->logging, SPAN_LOG_FLOW, "Map %3d - %5d %5d %5d\n", i, s->colour_map[3*i], s->colour_map[3*i + 1], s->colour_map[3*i + 2]);
378 }
379 #else
380 /* Sweep the colormap in the order that seems to work for l04x_02x.tif */
381 for (i = 0; i < s->colour_map_entries; i++)
382 {
383 s->colour_map[0*s->colour_map_entries + i] = (map_L[i] >> 8) & 0xFF;
384 s->colour_map[1*s->colour_map_entries + i] = (map_a[i] >> 8) & 0xFF;
385 s->colour_map[2*s->colour_map_entries + i] = (map_b[i] >> 8) & 0xFF;
386 }
387 #endif
388 lab_to_srgb(&s->lab_params, s->colour_map, s->colour_map, s->colour_map_entries);
389 for (i = 0; i < s->colour_map_entries; i++)
390 span_log(&s->logging, SPAN_LOG_FLOW, "Map %3d - %5d %5d %5d\n", i, s->colour_map[3*i], s->colour_map[3*i + 1], s->colour_map[3*i + 2]);
391 return 0;
392 }
393 /*- End of function --------------------------------------------------------*/
394 #endif
395
get_tiff_directory_info(t4_tx_state_t * s)396 static int get_tiff_directory_info(t4_tx_state_t *s)
397 {
398 #if defined(SPANDSP_SUPPORT_TIFF_FX)
399 static const char *tiff_fx_fax_profiles[] =
400 {
401 "???",
402 "profile S",
403 "profile F",
404 "profile J",
405 "profile C",
406 "profile L",
407 "profile M"
408 };
409 char *u;
410 char uu[10];
411 float *fl_parms;
412 toff_t diroff;
413 float lmin;
414 float lmax;
415 float amin;
416 float amax;
417 float bmin;
418 float bmax;
419 uint8_t parm8;
420 #endif
421 #if defined(SPANDSP_SUPPORT_TIFF_FX)
422 uint16_t parm16;
423 #endif
424 uint32_t parm32;
425 int best_x_entry;
426 int best_y_entry;
427 float x_resolution;
428 float y_resolution;
429 t4_tx_tiff_state_t *t;
430 uint16_t bits_per_sample;
431 uint16_t samples_per_pixel;
432 uint16_t res_unit;
433 uint16_t YCbCrSubsample_horiz;
434 uint16_t YCbCrSubsample_vert;
435
436 t = &s->tiff;
437 bits_per_sample = 1;
438 TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
439 samples_per_pixel = 1;
440 TIFFGetField(t->tiff_file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
441 if (samples_per_pixel == 1 && bits_per_sample == 1)
442 t->image_type = T4_IMAGE_TYPE_BILEVEL;
443 else if (samples_per_pixel == 3 && bits_per_sample == 1)
444 t->image_type = T4_IMAGE_TYPE_COLOUR_BILEVEL;
445 else if (samples_per_pixel == 4 && bits_per_sample == 1)
446 t->image_type = T4_IMAGE_TYPE_COLOUR_BILEVEL;
447 else if (samples_per_pixel == 1 && bits_per_sample == 8)
448 t->image_type = T4_IMAGE_TYPE_GRAY_8BIT;
449 else if (samples_per_pixel == 1 && bits_per_sample > 8)
450 t->image_type = T4_IMAGE_TYPE_GRAY_12BIT;
451 else if (samples_per_pixel == 3 && bits_per_sample == 8)
452 t->image_type = T4_IMAGE_TYPE_COLOUR_8BIT;
453 else if (samples_per_pixel == 3 && bits_per_sample > 8)
454 t->image_type = T4_IMAGE_TYPE_COLOUR_12BIT;
455 else
456 return -1;
457
458 #if defined(SPANDSP_SUPPORT_TIFF_FX)
459 parm16 = 0;
460 if (TIFFGetField(t->tiff_file, TIFFTAG_INDEXED, &parm16))
461 {
462 span_log(&s->logging, SPAN_LOG_FLOW, "Indexed %s (%u)\n", (parm16) ? "palette image" : "non-palette image", parm16);
463 if (parm16 == 1)
464 {
465 /* Its an indexed image, so its really a colour image, even though it may have only one sample per pixel */
466 if (samples_per_pixel == 1 && bits_per_sample == 8)
467 t->image_type = T4_IMAGE_TYPE_COLOUR_8BIT;
468 else if (samples_per_pixel == 1 && bits_per_sample > 8)
469 t->image_type = T4_IMAGE_TYPE_COLOUR_12BIT;
470 }
471 }
472 #endif
473
474 parm32 = 0;
475 TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
476 t->image_width = parm32;
477 parm32 = 0;
478 TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32);
479 t->image_length = parm32;
480
481 x_resolution = 0.0f;
482 TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);
483 y_resolution = 0.0f;
484 TIFFGetField(t->tiff_file, TIFFTAG_YRESOLUTION, &y_resolution);
485 res_unit = RESUNIT_INCH;
486 TIFFGetField(t->tiff_file, TIFFTAG_RESOLUTIONUNIT, &res_unit);
487
488 t->x_resolution = x_resolution*100.0f;
489 t->y_resolution = y_resolution*100.0f;
490 if (res_unit == RESUNIT_INCH)
491 {
492 t->x_resolution /= CM_PER_INCH;
493 t->y_resolution /= CM_PER_INCH;
494 }
495
496 if (((best_x_entry = match_resolution(t->x_resolution, x_res_table)) >= 0)
497 &&
498 ((best_y_entry = match_resolution(t->y_resolution, y_res_table)) >= 0))
499 {
500 t->resolution_code = resolution_map[best_y_entry][best_x_entry];
501 }
502 else
503 {
504 t->resolution_code = 0;
505 }
506
507 t->photo_metric = PHOTOMETRIC_MINISWHITE;
508 TIFFGetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, &t->photo_metric);
509
510 /* The default luminant is D50 */
511 set_lab_illuminant(&s->lab_params, 96.422f, 100.000f, 82.521f);
512 set_lab_gamut(&s->lab_params, 0, 100, -85, 85, -75, 125, false);
513
514 t->compression = -1;
515 TIFFGetField(t->tiff_file, TIFFTAG_COMPRESSION, &t->compression);
516 switch (t->compression)
517 {
518 case COMPRESSION_CCITT_T4:
519 span_log(&s->logging, SPAN_LOG_FLOW, "T.4\n");
520 break;
521 case COMPRESSION_CCITT_T6:
522 span_log(&s->logging, SPAN_LOG_FLOW, "T.6\n");
523 break;
524 case COMPRESSION_T85:
525 span_log(&s->logging, SPAN_LOG_FLOW, "T.85\n");
526 break;
527 case COMPRESSION_T43:
528 span_log(&s->logging, SPAN_LOG_FLOW, "T.43\n");
529 break;
530 case COMPRESSION_JPEG:
531 span_log(&s->logging, SPAN_LOG_FLOW, "JPEG\n");
532 if (t->photo_metric == PHOTOMETRIC_ITULAB)
533 span_log(&s->logging, SPAN_LOG_FLOW, "ITULAB\n");
534 break;
535 case COMPRESSION_NONE:
536 span_log(&s->logging, SPAN_LOG_FLOW, "No compression\n");
537 break;
538 default:
539 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected compression %d\n", t->compression);
540 break;
541 }
542
543 #if defined(SPANDSP_SUPPORT_TIFF_FX)
544 read_colour_map(s, bits_per_sample);
545 #endif
546
547 YCbCrSubsample_horiz = 0;
548 YCbCrSubsample_vert = 0;
549 if (TIFFGetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, &YCbCrSubsample_horiz, &YCbCrSubsample_vert))
550 span_log(&s->logging, SPAN_LOG_FLOW, "Subsampling %d %d\n", YCbCrSubsample_horiz, YCbCrSubsample_vert);
551
552 t->fill_order = FILLORDER_LSB2MSB;
553
554 #if defined(SPANDSP_SUPPORT_TIFF_FX)
555 if (TIFFGetField(t->tiff_file, TIFFTAG_PROFILETYPE, &parm32))
556 span_log(&s->logging, SPAN_LOG_FLOW, "Profile type %u\n", parm32);
557 if (TIFFGetField(t->tiff_file, TIFFTAG_FAXPROFILE, &parm8))
558 span_log(&s->logging, SPAN_LOG_FLOW, "FAX profile %s (%u)\n", tiff_fx_fax_profiles[parm8], parm8);
559
560 if (TIFFGetField(t->tiff_file, TIFFTAG_CODINGMETHODS, &parm32))
561 span_log(&s->logging, SPAN_LOG_FLOW, "Coding methods 0x%x\n", parm32);
562 if (TIFFGetField(t->tiff_file, TIFFTAG_VERSIONYEAR, &u))
563 {
564 memcpy(uu, u, 4);
565 uu[4] = '\0';
566 span_log(&s->logging, SPAN_LOG_FLOW, "Version year \"%s\"\n", uu);
567 }
568 if (TIFFGetField(t->tiff_file, TIFFTAG_MODENUMBER, &parm8))
569 span_log(&s->logging, SPAN_LOG_FLOW, "Mode number %u\n", parm8);
570
571 switch (t->photo_metric)
572 {
573 case PHOTOMETRIC_ITULAB:
574 #if 1
575 /* 8 bit version */
576 lmin = 0.0f;
577 lmax = 100.0f;
578 amin = -21760.0f/255.0f;
579 amax = 21590.0f/255.0f;
580 bmin = -19200.0f/255.0f;
581 bmax = 31800.0f/255.0f;
582 #else
583 /* 12 bit version */
584 lmin = 0.0f;
585 lmax = 100.0f;
586 amin = -348160.0f/4095.0f
587 amax = 347990.0f/4095.0f
588 bmin = -307200.0f/4095.0f
589 bmax = 511800.0f/4095.0f
590 #endif
591 break;
592 default:
593 lmin = 0.0f;
594 lmax = 0.0f;
595 amin = 0.0f;
596 amax = 0.0f;
597 bmin = 0.0f;
598 bmax = 0.0f;
599 break;
600 }
601
602 if (TIFFGetField(t->tiff_file, TIFFTAG_DECODE, &parm16, &fl_parms))
603 {
604 lmin = fl_parms[0];
605 lmax = fl_parms[1];
606 amin = fl_parms[2];
607 amax = fl_parms[3];
608 bmin = fl_parms[4];
609 bmax = fl_parms[5];
610 span_log(&s->logging, SPAN_LOG_FLOW, "Got decode tag %f %f %f %f %f %f\n", lmin, lmax, amin, amax, bmin, bmax);
611 }
612
613 /* TIFFTAG_IMAGEBASECOLOR */
614
615 if (TIFFGetField(t->tiff_file, TIFFTAG_T82OPTIONS, &parm32))
616 span_log(&s->logging, SPAN_LOG_FLOW, "T.82 options 0x%x\n", parm32);
617
618 /* TIFFTAG_STRIPROWCOUNTS */
619 /* TIFFTAG_IMAGELAYER */
620
621 /* If global parameters are present they should only be on the first page of the file.
622 However, as we scan the file we might as well look for them on any page. */
623 diroff = 0;
624 if (TIFFGetField(t->tiff_file, TIFFTAG_GLOBALPARAMETERSIFD, &diroff))
625 {
626 #if TIFFLIB_VERSION >= 20120922 && defined(HAVE_TIF_DIR_H)
627 if (!TIFFReadCustomDirectory(t->tiff_file, diroff, &tiff_fx_field_array))
628 {
629 span_log(&s->logging, SPAN_LOG_FLOW, "Global parameter read failed\n");
630 }
631 else
632 {
633 span_log(&s->logging, SPAN_LOG_FLOW, "Global parameters\n");
634 if (TIFFGetField(t->tiff_file, TIFFTAG_PROFILETYPE, &parm32))
635 span_log(&s->logging, SPAN_LOG_FLOW, " Profile type %u\n", parm32);
636 if (TIFFGetField(t->tiff_file, TIFFTAG_FAXPROFILE, &parm8))
637 span_log(&s->logging, SPAN_LOG_FLOW, " FAX profile %s (%u)\n", tiff_fx_fax_profiles[parm8], parm8);
638 if (TIFFGetField(t->tiff_file, TIFFTAG_CODINGMETHODS, &parm32))
639 span_log(&s->logging, SPAN_LOG_FLOW, " Coding methods 0x%x\n", parm32);
640 if (TIFFGetField(t->tiff_file, TIFFTAG_VERSIONYEAR, &u))
641 {
642 memcpy(uu, u, 4);
643 uu[4] = '\0';
644 span_log(&s->logging, SPAN_LOG_FLOW, " Version year \"%s\"\n", uu);
645 }
646 if (TIFFGetField(t->tiff_file, TIFFTAG_MODENUMBER, &parm8))
647 span_log(&s->logging, SPAN_LOG_FLOW, " Mode number %u\n", parm8);
648
649 if (!TIFFSetDirectory(t->tiff_file, (tdir_t) s->current_page))
650 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set directory to page %d\n", s->current_page);
651 }
652 #endif
653 }
654 #endif
655 return 0;
656 }
657 /*- End of function --------------------------------------------------------*/
658
test_tiff_directory_info(t4_tx_state_t * s)659 static int test_tiff_directory_info(t4_tx_state_t *s)
660 {
661 uint16_t res_unit;
662 uint32_t parm32;
663 uint16_t bits_per_sample;
664 uint16_t samples_per_pixel;
665 int image_type;
666 float x_resolution;
667 float y_resolution;
668 t4_tx_tiff_state_t *t;
669
670 t = &s->tiff;
671 bits_per_sample = 1;
672 TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
673 samples_per_pixel = 1;
674 TIFFGetField(t->tiff_file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
675 if (samples_per_pixel == 1 && bits_per_sample == 1)
676 image_type = T4_IMAGE_TYPE_BILEVEL;
677 else if (samples_per_pixel == 3 && bits_per_sample == 1)
678 image_type = T4_IMAGE_TYPE_COLOUR_BILEVEL;
679 else if (samples_per_pixel == 4 && bits_per_sample == 1)
680 image_type = T4_IMAGE_TYPE_COLOUR_BILEVEL;
681 else if (samples_per_pixel == 1 && bits_per_sample == 8)
682 image_type = T4_IMAGE_TYPE_GRAY_8BIT;
683 else if (samples_per_pixel == 1 && bits_per_sample > 8)
684 image_type = T4_IMAGE_TYPE_GRAY_12BIT;
685 else if (samples_per_pixel == 3 && bits_per_sample == 8)
686 image_type = T4_IMAGE_TYPE_COLOUR_8BIT;
687 else if (samples_per_pixel == 3 && bits_per_sample > 8)
688 image_type = T4_IMAGE_TYPE_COLOUR_12BIT;
689 else
690 image_type = -1;
691 if (t->image_type != image_type)
692 return 1;
693
694 parm32 = 0;
695 TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
696 if (s->tiff.image_width != (int) parm32)
697 return 2;
698
699 x_resolution = 0.0f;
700 TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);
701 y_resolution = 0.0f;
702 TIFFGetField(t->tiff_file, TIFFTAG_YRESOLUTION, &y_resolution);
703 res_unit = RESUNIT_INCH;
704 TIFFGetField(t->tiff_file, TIFFTAG_RESOLUTIONUNIT, &res_unit);
705
706 x_resolution *= 100.0f;
707 y_resolution *= 100.0f;
708 if (res_unit == RESUNIT_INCH)
709 {
710 x_resolution /= CM_PER_INCH;
711 y_resolution /= CM_PER_INCH;
712 }
713 if (s->tiff.x_resolution != (int) x_resolution)
714 return 3;
715 if (s->tiff.y_resolution != (int) y_resolution)
716 return 4;
717
718 return 0;
719 }
720 /*- End of function --------------------------------------------------------*/
721
get_tiff_total_pages(t4_tx_state_t * s)722 static int get_tiff_total_pages(t4_tx_state_t *s)
723 {
724 int max;
725
726 /* Each page *should* contain the total number of pages, but can this be
727 trusted? Some files say 0. Actually searching for the last page is
728 more reliable. */
729 max = 0;
730 while (TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) max))
731 max++;
732 /* Back to the previous page */
733 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page))
734 return -1;
735 return max;
736 }
737 /*- End of function --------------------------------------------------------*/
738
open_tiff_input_file(t4_tx_state_t * s,const char * file)739 static int open_tiff_input_file(t4_tx_state_t *s, const char *file)
740 {
741 if ((s->tiff.tiff_file = TIFFOpen(file, "r")) == NULL)
742 return -1;
743 return 0;
744 }
745 /*- End of function --------------------------------------------------------*/
746
metadata_row_read_handler(void * user_data,uint8_t buf[],size_t len)747 static int metadata_row_read_handler(void *user_data, uint8_t buf[], size_t len)
748 {
749 t4_tx_state_t *s;
750
751 s = (t4_tx_state_t *) user_data;
752 if (s->tiff.row >= s->metadata.image_length)
753 return 0;
754 memcpy(buf, &s->tiff.image_buffer[s->tiff.row*len], len);
755 s->tiff.row++;
756 return len;
757 }
758 /*- End of function --------------------------------------------------------*/
759
tiff_row_read_handler(void * user_data,uint8_t buf[],size_t len)760 static int tiff_row_read_handler(void *user_data, uint8_t buf[], size_t len)
761 {
762 t4_tx_state_t *s;
763 int i;
764 int j;
765
766 s = (t4_tx_state_t *) user_data;
767 if (s->tiff.row >= s->tiff.image_length)
768 return 0;
769 if (s->tiff.image_buffer == NULL)
770 return 0;
771 memcpy(buf, &s->tiff.image_buffer[s->tiff.row*len], len);
772 s->tiff.row++;
773
774 /* If this is a bi-level image which has more vertical resolution than the
775 far end will accept, we need to squash it down to size. */
776 for (i = 1; i < s->row_squashing_ratio && s->tiff.row < s->tiff.image_length; i++)
777 {
778 for (j = 0; j < len; j++)
779 buf[j] |= s->tiff.image_buffer[s->tiff.row*len + j];
780 s->tiff.row++;
781 }
782 return len;
783 }
784 /*- End of function --------------------------------------------------------*/
785
translate_row_read2(void * user_data,uint8_t buf[],size_t len)786 static int translate_row_read2(void *user_data, uint8_t buf[], size_t len)
787 {
788 t4_tx_state_t *s;
789
790 s = (t4_tx_state_t *) user_data;
791 memcpy(buf, &s->pack_buf[s->pack_ptr], len);
792 s->pack_ptr += len;
793 s->pack_row++;
794 return len;
795 }
796 /*- End of function --------------------------------------------------------*/
797
translate_row_read(void * user_data,uint8_t buf[],size_t len)798 static int translate_row_read(void *user_data, uint8_t buf[], size_t len)
799 {
800 t4_tx_state_t *s;
801 int i;
802 int j;
803
804 s = (t4_tx_state_t *) user_data;
805
806 if (s->tiff.raw_row >= s->tiff.image_length)
807 return 0;
808
809 if (TIFFReadScanline(s->tiff.tiff_file, buf, s->tiff.raw_row, 0) < 0)
810 return 0;
811 s->tiff.raw_row++;
812
813 /* If this is a bi-level image which is stretched more vertically than we are able
814 to send we need to squash it down to size. */
815 for (i = 1; i < s->row_squashing_ratio; i++)
816 {
817 #if defined(_MSC_VER)
818 uint8_t *extra_buf = (uint8_t *) _alloca(len);
819 #else
820 uint8_t extra_buf[len];
821 #endif
822
823 if (TIFFReadScanline(s->tiff.tiff_file, extra_buf, s->tiff.raw_row, 0) < 0)
824 return 0;
825 s->tiff.raw_row++;
826 /* We know this is a bi-level image if we are squashing */
827 for (j = 0; j < s->tiff.image_width/8; j++)
828 buf[j] |= extra_buf[s->tiff.image_width/8 + j];
829 }
830 if (s->apply_lab)
831 lab_to_srgb(&s->lab_params, buf, buf, len/3);
832 return len;
833 }
834 /*- End of function --------------------------------------------------------*/
835
packing_row_write_handler(void * user_data,const uint8_t buf[],size_t len)836 static int packing_row_write_handler(void *user_data, const uint8_t buf[], size_t len)
837 {
838 packer_t *s;
839
840 s = (packer_t *) user_data;
841 memcpy(&s->buf[s->ptr], buf, len);
842 s->ptr += len;
843 s->row++;
844 return 0;
845 }
846 /*- End of function --------------------------------------------------------*/
847
embedded_comment_handler(void * user_data,const uint8_t buf[],size_t len)848 static int embedded_comment_handler(void *user_data, const uint8_t buf[], size_t len)
849 {
850 t4_tx_state_t *s;
851
852 s = (t4_tx_state_t *) user_data;
853 if (buf)
854 span_log(&s->logging, SPAN_LOG_WARNING, "T.85 comment (%d): %s\n", (int) len, buf);
855 else
856 span_log(&s->logging, SPAN_LOG_WARNING, "T.85 comment (%d): ---\n", (int) len);
857 return 0;
858 }
859 /*- End of function --------------------------------------------------------*/
860
read_tiff_raw_image(t4_tx_state_t * s)861 static int read_tiff_raw_image(t4_tx_state_t *s)
862 {
863 int num_strips;
864 int total_len;
865 int len;
866 int i;
867
868 num_strips = TIFFNumberOfStrips(s->tiff.tiff_file);
869 total_len = 0;
870 for (i = 0; i < num_strips; i++)
871 total_len += TIFFRawStripSize(s->tiff.tiff_file, i);
872 if ((s->no_encoder.buf = span_realloc(s->no_encoder.buf, total_len)) == NULL)
873 return -1;
874 total_len = 0;
875 for (i = 0; i < num_strips; i++, total_len += len)
876 {
877 len = TIFFRawStripSize(s->tiff.tiff_file, i);
878 if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &s->no_encoder.buf[total_len], len)) < 0)
879 {
880 span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadRawStrip error.\n", s->tiff.file);
881 return -1;
882 }
883 }
884 s->no_encoder.buf_len = total_len;
885 s->no_encoder.buf_ptr = 0;
886 return 0;
887 }
888 /*- End of function --------------------------------------------------------*/
889
read_tiff_t85_image(t4_tx_state_t * s)890 static int read_tiff_t85_image(t4_tx_state_t *s)
891 {
892 int biggest;
893 int num_strips;
894 int len;
895 int i;
896 int result;
897 uint8_t *t;
898 uint8_t *raw_data;
899 t85_decode_state_t t85;
900 packer_t pack;
901
902 /* Size up and allocate the buffer for the raw data */
903 num_strips = TIFFNumberOfStrips(s->tiff.tiff_file);
904 biggest = 0;
905 for (i = 0; i < num_strips; i++)
906 {
907 len = TIFFRawStripSize(s->tiff.tiff_file, i);
908 if (len > biggest)
909 biggest = len;
910 }
911 if ((raw_data = span_alloc(biggest)) == NULL)
912 return -1;
913
914 s->tiff.image_size = s->tiff.image_length*((s->tiff.image_width + 7)/8);
915 if (s->tiff.image_size >= s->tiff.image_buffer_size)
916 {
917 if ((t = span_realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
918 {
919 span_free(raw_data);
920 return -1;
921 }
922 s->tiff.image_buffer_size = s->tiff.image_size;
923 s->tiff.image_buffer = t;
924 }
925
926 pack.buf = s->tiff.image_buffer;
927 pack.ptr = 0;
928 pack.size = s->tiff.image_size;
929 pack.row = 0;
930 t85_decode_init(&t85, packing_row_write_handler, &pack);
931 t85_decode_set_comment_handler(&t85, 1000, embedded_comment_handler, s);
932 t85_decode_set_image_size_constraints(&t85, s->tiff.image_width, s->tiff.image_length);
933 result = -1;
934 for (i = 0; i < num_strips; i++)
935 {
936 len = TIFFRawStripSize(s->tiff.tiff_file, i);
937 if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, raw_data, len)) < 0)
938 {
939 span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadRawStrip error.\n", s->tiff.file);
940 span_free(raw_data);
941 return -1;
942 }
943 if ((result = t85_decode_put(&t85, raw_data, len)) != T4_DECODE_MORE_DATA)
944 break;
945 }
946 if (result == T4_DECODE_MORE_DATA)
947 t85_decode_put(&t85, NULL, 0);
948
949 len = t85_decode_get_compressed_image_size(&t85);
950 span_log(&s->logging, SPAN_LOG_WARNING, "Compressed image is %d bytes, %d rows\n", len/8, s->tiff.image_length);
951 t85_decode_release(&t85);
952 span_free(raw_data);
953 return 0;
954 }
955 /*- End of function --------------------------------------------------------*/
956
957 #if defined(SPANDSP_SUPPORT_T43)
read_tiff_t43_image(t4_tx_state_t * s)958 static int read_tiff_t43_image(t4_tx_state_t *s)
959 {
960 int biggest;
961 int num_strips;
962 int len;
963 int i;
964 int result;
965 uint8_t *t;
966 uint8_t *raw_data;
967 logging_state_t *logging;
968 t43_decode_state_t t43;
969 packer_t pack;
970 uint16_t bits_per_sample;
971 uint16_t samples_per_pixel;
972
973 bits_per_sample = 1;
974 TIFFGetField(s->tiff.tiff_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
975 samples_per_pixel = 3;
976 TIFFGetField(s->tiff.tiff_file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
977
978 samples_per_pixel = 3;
979
980 num_strips = TIFFNumberOfStrips(s->tiff.tiff_file);
981 biggest = 0;
982 for (i = 0; i < num_strips; i++)
983 {
984 len = TIFFRawStripSize(s->tiff.tiff_file, i);
985 if (len > biggest)
986 biggest = len;
987 }
988 if ((raw_data = span_alloc(biggest)) == NULL)
989 return -1;
990
991 s->tiff.image_size = samples_per_pixel*s->tiff.image_width*s->tiff.image_length;
992 if (s->tiff.image_size >= s->tiff.image_buffer_size)
993 {
994 if ((t = span_realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
995 {
996 span_free(raw_data);
997 return -1;
998 }
999 s->tiff.image_buffer_size = s->tiff.image_size;
1000 s->tiff.image_buffer = t;
1001 }
1002
1003 t43_decode_init(&t43, packing_row_write_handler, &pack);
1004 t43_decode_set_comment_handler(&t43, 1000, embedded_comment_handler, NULL);
1005 t43_decode_set_image_size_constraints(&t43, s->tiff.image_width, s->tiff.image_length);
1006 logging = t43_decode_get_logging_state(&t43);
1007 span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
1008
1009 pack.buf = s->tiff.image_buffer;
1010 pack.ptr = 0;
1011 pack.size = s->tiff.image_size;
1012 pack.row = 0;
1013
1014 result = -1;
1015 for (i = 0; i < num_strips; i++)
1016 {
1017 len = TIFFRawStripSize(s->tiff.tiff_file, i);
1018 if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, raw_data, len)) < 0)
1019 {
1020 span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadRawStrip error.\n", s->tiff.file);
1021 span_free(raw_data);
1022 return -1;
1023 }
1024 if ((result = t43_decode_put(&t43, raw_data, len)) != T4_DECODE_MORE_DATA)
1025 break;
1026 }
1027 if (result == T4_DECODE_MORE_DATA)
1028 result = t43_decode_put(&t43, NULL, 0);
1029
1030 t43_decode_release(&t43);
1031 span_free(raw_data);
1032 return s->tiff.image_size;
1033 }
1034 /*- End of function --------------------------------------------------------*/
1035 #endif
1036
read_tiff_t42_t81_image(t4_tx_state_t * s)1037 static int read_tiff_t42_t81_image(t4_tx_state_t *s)
1038 {
1039 int total_len;
1040 int len;
1041 int i;
1042 int num_strips;
1043 int total_image_len;
1044 uint8_t *t;
1045 uint8_t *raw_data;
1046 uint8_t *jpeg_table;
1047 uint32_t jpeg_table_len;
1048 packer_t pack;
1049 uint16_t bits_per_sample;
1050 uint16_t samples_per_pixel;
1051 t42_decode_state_t t42;
1052
1053 bits_per_sample = 1;
1054 TIFFGetField(s->tiff.tiff_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
1055 samples_per_pixel = 1;
1056 TIFFGetField(s->tiff.tiff_file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
1057
1058 num_strips = TIFFNumberOfStrips(s->tiff.tiff_file);
1059 total_image_len = 0;
1060 jpeg_table_len = 0;
1061 if (TIFFGetField(s->tiff.tiff_file, TIFFTAG_JPEGTABLES, &jpeg_table_len, &jpeg_table))
1062 {
1063 total_image_len += (jpeg_table_len - 4);
1064 span_log(&s->logging, SPAN_LOG_FLOW, "JPEG tables %u\n", jpeg_table_len);
1065 }
1066
1067 for (i = 0; i < num_strips; i++)
1068 total_image_len += TIFFRawStripSize(s->tiff.tiff_file, i);
1069 if ((raw_data = span_alloc(total_image_len)) == NULL)
1070 return -1;
1071
1072 total_len = 0;
1073 if (jpeg_table_len > 0)
1074 total_len += jpeg_table_len - 4;
1075 for (i = 0; i < num_strips; i++, total_len += len)
1076 {
1077 if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &raw_data[total_len], total_image_len - total_len)) < 0)
1078 {
1079 span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadRawStrip error.\n", s->tiff.file);
1080 span_free(raw_data);
1081 return -1;
1082 }
1083 }
1084 if (jpeg_table_len > 0)
1085 memcpy(raw_data, jpeg_table, jpeg_table_len - 2);
1086
1087 if (total_len != total_image_len)
1088 span_log(&s->logging, SPAN_LOG_FLOW, "Size mismatch %d %d\n", (int) total_len, (int) total_image_len);
1089
1090 s->tiff.image_size = samples_per_pixel*s->tiff.image_width*s->tiff.image_length;
1091 if (s->tiff.image_size >= s->tiff.image_buffer_size)
1092 {
1093 if ((t = span_realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
1094 {
1095 span_free(raw_data);
1096 return -1;
1097 }
1098 s->tiff.image_buffer_size = s->tiff.image_size;
1099 s->tiff.image_buffer = t;
1100 }
1101
1102 t42_decode_init(&t42, packing_row_write_handler, &pack);
1103
1104 pack.buf = s->tiff.image_buffer;
1105 pack.ptr = 0;
1106 pack.row = 0;
1107
1108 t42_decode_put(&t42, raw_data, total_image_len);
1109 t42_decode_put(&t42, NULL, 0);
1110
1111 t42_decode_release(&t42);
1112 span_free(raw_data);
1113 return s->tiff.image_size;
1114 }
1115 /*- End of function --------------------------------------------------------*/
1116
read_tiff_decompressed_image(t4_tx_state_t * s)1117 static int read_tiff_decompressed_image(t4_tx_state_t *s)
1118 {
1119 int total_len;
1120 int len;
1121 int num_strips;
1122 int i;
1123 uint8_t *t;
1124
1125 /* Decode the whole image into a buffer */
1126 /* Let libtiff handle the decompression */
1127 s->tiff.image_size = s->tiff.image_length*TIFFScanlineSize(s->tiff.tiff_file);
1128 if (s->tiff.image_size >= s->tiff.image_buffer_size)
1129 {
1130 if ((t = span_realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
1131 return -1;
1132 s->tiff.image_buffer_size = s->tiff.image_size;
1133 s->tiff.image_buffer = t;
1134 }
1135
1136 /* Allow for the image being stored in multiple strips. */
1137 num_strips = TIFFNumberOfStrips(s->tiff.tiff_file);
1138 for (i = 0, total_len = 0; i < num_strips; i++, total_len += len)
1139 {
1140 if ((len = TIFFReadEncodedStrip(s->tiff.tiff_file, i, &s->tiff.image_buffer[total_len], s->tiff.image_size - total_len)) < 0)
1141 {
1142 span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadEncodedStrip error.\n", s->tiff.file);
1143 return -1;
1144 }
1145 }
1146 /* We might need to flip all the bits, so 1 = black and 0 = white. */
1147 if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL && s->tiff.photo_metric != PHOTOMETRIC_MINISWHITE)
1148 {
1149 span_log(&s->logging, SPAN_LOG_FLOW, "%s: Photometric needs swapping.\n", s->tiff.file);
1150 for (i = 0; i < s->tiff.image_size; i++)
1151 s->tiff.image_buffer[i] = ~s->tiff.image_buffer[i];
1152 s->tiff.photo_metric = PHOTOMETRIC_MINISWHITE;
1153 }
1154 /* We might need to bit reverse each of the bytes of the image. */
1155 if (s->tiff.fill_order != FILLORDER_LSB2MSB)
1156 bit_reverse(s->tiff.image_buffer, s->tiff.image_buffer, s->tiff.image_size);
1157 return 0;
1158 }
1159 /*- End of function --------------------------------------------------------*/
1160
read_tiff_image(t4_tx_state_t * s)1161 static int read_tiff_image(t4_tx_state_t *s)
1162 {
1163 int total_len;
1164 int i;
1165 int alter_image;
1166 uint8_t *t;
1167
1168 if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width)
1169 {
1170 /* We need to rework the image, so it can't pass directly through */
1171 alter_image = true;
1172 image_translate_restart(&s->translator, s->tiff.image_length);
1173 s->metadata.image_length = image_translate_get_output_length(&s->translator);
1174 image_translate_set_row_read_handler(&s->translator, translate_row_read2, s);
1175 }
1176 else
1177 {
1178 alter_image = false;
1179 s->metadata.image_length = s->tiff.image_length;
1180 }
1181 s->pack_buf = NULL;
1182 s->pack_ptr = 0;
1183 s->pack_row = 0;
1184
1185 s->apply_lab = false;
1186 if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL)
1187 {
1188 /* If colour/gray scale is supported we may be able to send the image as it is, perhaps after
1189 a resizing. Otherwise we need to resize it, and squash it to a bilevel image. */
1190 if (s->tiff.compression == COMPRESSION_JPEG && s->tiff.photo_metric == PHOTOMETRIC_ITULAB)
1191 {
1192 if (alter_image)
1193 {
1194 if (read_tiff_t42_t81_image(s) < 0)
1195 return -1;
1196 s->pack_buf = s->tiff.image_buffer;
1197 }
1198 else
1199 {
1200 /* Read the raw image, and send it as is */
1201 if (read_tiff_raw_image(s) < 0)
1202 return -1;
1203 }
1204 }
1205 #if defined(SPANDSP_SUPPORT_T43)
1206 else if (s->tiff.compression == COMPRESSION_T43)
1207 {
1208 if (alter_image)
1209 {
1210 if ( read_tiff_t43_image(s) < 0)
1211 return -1;
1212 s->pack_buf = s->tiff.image_buffer;
1213 }
1214 else
1215 {
1216 /* Read the raw image, and send it as is */
1217 if (read_tiff_raw_image(s) < 0)
1218 return -1;
1219 }
1220 }
1221 #endif
1222 #if defined(SPANDSP_SUPPORT_T45)
1223 else if (s->tiff.compression == COMPRESSION_T45)
1224 {
1225 if (alter_image)
1226 {
1227 if (read_tiff_t45_image(s) < 0)
1228 return -1;
1229 s->pack_buf = s->tiff.image_buffer;
1230 }
1231 else
1232 {
1233 /* Read the raw image, and send it as is */
1234 if (read_tiff_raw_image(s) < 0)
1235 return -1;
1236 }
1237 }
1238 #endif
1239 else
1240 {
1241 /* Let libtiff handle the decompression */
1242 TIFFSetField(s->tiff.tiff_file, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
1243 if (alter_image)
1244 {
1245 image_translate_set_row_read_handler(&s->translator, translate_row_read, s);
1246 }
1247 else
1248 {
1249 if (read_tiff_decompressed_image(s) < 0)
1250 return -1;
1251 }
1252 }
1253
1254 set_image_width(s, s->metadata.image_width);
1255 set_image_length(s, s->metadata.image_length);
1256 t4_tx_set_image_type(s, s->metadata.image_type);
1257 if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL)
1258 {
1259 /* We need to dither this image down to pure black and white, possibly resizing it
1260 along the way. */
1261 s->tiff.image_size = (s->metadata.image_width*s->metadata.image_length + 7)/8;
1262 if (s->tiff.image_size >= s->tiff.image_buffer_size)
1263 {
1264 if ((t = span_realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
1265 return -1;
1266 s->tiff.image_buffer_size = s->tiff.image_size;
1267 s->tiff.image_buffer = t;
1268 }
1269 s->tiff.raw_row = 0;
1270 switch (s->tiff.photo_metric)
1271 {
1272 case PHOTOMETRIC_CIELAB:
1273 /* The default luminant is D50 */
1274 set_lab_illuminant(&s->lab_params, 96.422f, 100.000f, 82.521f);
1275 set_lab_gamut(&s->lab_params, 0, 100, -128, 127, -128, 127, true);
1276 s->apply_lab = true;
1277 break;
1278 case PHOTOMETRIC_ITULAB:
1279 /* The default luminant is D50 */
1280 set_lab_illuminant(&s->lab_params, 96.422f, 100.000f, 82.521f);
1281 set_lab_gamut(&s->lab_params, 0, 100, -85, 85, -75, 125, false);
1282 s->apply_lab = true;
1283 break;
1284 }
1285 total_len = 0;
1286 for (i = 0; i < s->metadata.image_length; i++)
1287 total_len += image_translate_row(&s->translator, &s->tiff.image_buffer[total_len], s->metadata.image_width/8);
1288 image_translate_release(&s->translator);
1289 s->row_handler = metadata_row_read_handler;
1290 s->row_handler_user_data = (void *) s;
1291 }
1292 else
1293 {
1294 if (alter_image)
1295 {
1296 total_len = 0;
1297 s->tiff.image_buffer = span_realloc(s->tiff.image_buffer, s->metadata.image_width*s->metadata.image_length*3);
1298 for (i = 0; i < s->metadata.image_length; i++)
1299 total_len += image_translate_row(&s->translator, &s->tiff.image_buffer[total_len], s->metadata.image_width);
1300 image_translate_release(&s->translator);
1301 s->row_handler = metadata_row_read_handler;
1302 s->row_handler_user_data = (void *) s;
1303 }
1304 else
1305 {
1306 s->row_handler = tiff_row_read_handler;
1307 s->row_handler_user_data = (void *) s;
1308 }
1309 }
1310 }
1311 else
1312 {
1313 /* The original image is a bi-level one. We can't really rescale it, as that works out
1314 really poorly for a bi-level image. It has to be used in its original form. The only
1315 practical exception is to conver a superfine resolution image to a fine resolution one,
1316 or a fine image to a standard resolution one. We could pad slightly short rows or crop
1317 slightly long one, but lets not bother. */
1318 switch (s->tiff.compression)
1319 {
1320 #if defined(SPANDSP_SUPPORT_T88)
1321 case COMPRESSION_T88:
1322 switch (s->metadata.compression)
1323 {
1324 case T4_COMPRESSION_T88:
1325 /* Read the raw image, and send it as is */
1326 if (read_tiff_raw_image(s) < 0)
1327 return -1;
1328 break;
1329 default:
1330 /* libtiff probably cannot decompress T.88, so we must handle it ourselves */
1331 /* Decode the whole image into a buffer */
1332 if (read_tiff_t88_image(s) < 0)
1333 return -1;
1334 break;
1335 }
1336 break;
1337 #endif
1338 case COMPRESSION_T85:
1339 switch (s->metadata.compression)
1340 {
1341 case T4_COMPRESSION_T85:
1342 case T4_COMPRESSION_T85_L0:
1343 /* Read the raw image, and send it as is */
1344 if (read_tiff_raw_image(s) < 0)
1345 return -1;
1346 break;
1347 default:
1348 /* libtiff probably cannot decompress T.85, so we must handle it ourselves */
1349 /* Decode the whole image into a buffer */
1350 if (read_tiff_t85_image(s) < 0)
1351 return -1;
1352 break;
1353 }
1354 break;
1355 #if 0
1356 case COMPRESSION_CCITT_T6:
1357 switch (s->metadata.compression)
1358 {
1359 case T4_COMPRESSION_T6:
1360 /* Read the raw image, and send it as is */
1361 if (read_tiff_raw_image(s) < 0)
1362 return -1;
1363 break;
1364 default:
1365 /* Decode the whole image into a buffer */
1366 /* Let libtiff handle the decompression */
1367 if (read_tiff_decompressed_image(s) < 0)
1368 return -1;
1369 break;
1370 }
1371 break;
1372 #endif
1373 default:
1374 /* Decode the whole image into a buffer */
1375 /* Let libtiff handle the decompression */
1376 if (read_tiff_decompressed_image(s) < 0)
1377 return -1;
1378 break;
1379 }
1380 }
1381 s->tiff.row = 0;
1382 return s->metadata.image_length;
1383 }
1384 /*- End of function --------------------------------------------------------*/
1385
tiff_tx_release(t4_tx_state_t * s)1386 static void tiff_tx_release(t4_tx_state_t *s)
1387 {
1388 if (s->tiff.tiff_file)
1389 {
1390 TIFFClose(s->tiff.tiff_file);
1391 s->tiff.tiff_file = NULL;
1392 if (s->tiff.file)
1393 span_free((char *) s->tiff.file);
1394 s->tiff.file = NULL;
1395 }
1396 if (s->tiff.image_buffer)
1397 {
1398 span_free(s->tiff.image_buffer);
1399 s->tiff.image_buffer = NULL;
1400 s->tiff.image_size = 0;
1401 s->tiff.image_buffer_size = 0;
1402 }
1403 }
1404 /*- End of function --------------------------------------------------------*/
1405
set_row_read_handler(t4_tx_state_t * s,t4_row_read_handler_t handler,void * user_data)1406 static int set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler, void *user_data)
1407 {
1408 switch (s->metadata.compression)
1409 {
1410 case T4_COMPRESSION_T4_1D:
1411 case T4_COMPRESSION_T4_2D:
1412 case T4_COMPRESSION_T6:
1413 return t4_t6_encode_set_row_read_handler(&s->encoder.t4_t6, handler, user_data);
1414 case T4_COMPRESSION_T85:
1415 case T4_COMPRESSION_T85_L0:
1416 return t85_encode_set_row_read_handler(&s->encoder.t85, handler, user_data);
1417 #if defined(SPANDSP_SUPPORT_T88)
1418 case T4_COMPRESSION_T88:
1419 return t88_encode_set_row_read_handler(&s->encoder.t88, handler, user_data);
1420 #endif
1421 case T4_COMPRESSION_T42_T81:
1422 case T4_COMPRESSION_SYCC_T81:
1423 return t42_encode_set_row_read_handler(&s->encoder.t42, handler, user_data);
1424 case T4_COMPRESSION_T43:
1425 return t43_encode_set_row_read_handler(&s->encoder.t43, handler, user_data);
1426 #if defined(SPANDSP_SUPPORT_T45)
1427 case T4_COMPRESSION_T45:
1428 return t45_encode_set_row_read_handler(&s->encoder.t45, handler, user_data);
1429 #endif
1430 }
1431 return -1;
1432 }
1433 /*- End of function --------------------------------------------------------*/
1434
make_header(t4_tx_state_t * s)1435 static int make_header(t4_tx_state_t *s)
1436 {
1437 time_t now;
1438 struct tm tm;
1439 static const char *months[] =
1440 {
1441 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1442 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1443 };
1444
1445 if (s->header_text == NULL)
1446 {
1447 if ((s->header_text = span_alloc(132 + 1)) == NULL)
1448 return -1;
1449 }
1450 /* This is very English oriented, but then most FAX machines are, too. Some
1451 measure of i18n in the time and date, and even the header_info string, is
1452 entirely possible, although the font area would need some serious work to
1453 properly deal with East Asian script. There is no spec for what the header
1454 should contain, or how much of the page it might occupy. The present format
1455 follows the common practice of a few FAX machines. Nothing more. */
1456 time(&now);
1457 if (s->tz)
1458 tz_localtime(s->tz, &tm, now);
1459 else
1460 tm = *localtime(&now);
1461
1462 snprintf(s->header_text,
1463 132,
1464 " %2d-%s-%d %02d:%02d %-50s %-21s p.%d",
1465 tm.tm_mday,
1466 months[tm.tm_mon],
1467 tm.tm_year + 1900,
1468 tm.tm_hour,
1469 tm.tm_min,
1470 (s->header_info) ? s->header_info : "",
1471 (s->local_ident) ? s->local_ident : "",
1472 s->current_page + 1);
1473 return 0;
1474 }
1475 /*- End of function --------------------------------------------------------*/
1476
header_row_read_handler(void * user_data,uint8_t buf[],size_t len)1477 static int header_row_read_handler(void *user_data, uint8_t buf[], size_t len)
1478 {
1479 int y_repeats;
1480 int pattern;
1481 int pos;
1482 int row;
1483 int i;
1484 char *t;
1485 t4_tx_state_t *s;
1486
1487 s = (t4_tx_state_t *) user_data;
1488 switch (s->metadata.resolution_code)
1489 {
1490 default:
1491 case T4_RESOLUTION_100_100:
1492 y_repeats = 1;
1493 break;
1494 case T4_RESOLUTION_R8_STANDARD:
1495 case T4_RESOLUTION_200_100:
1496 y_repeats = 1;
1497 break;
1498 case T4_RESOLUTION_R8_FINE:
1499 case T4_RESOLUTION_200_200:
1500 y_repeats = 2;
1501 break;
1502 case T4_RESOLUTION_300_300:
1503 y_repeats = 3;
1504 break;
1505 case T4_RESOLUTION_R8_SUPERFINE:
1506 case T4_RESOLUTION_200_400:
1507 y_repeats = 4;
1508 break;
1509 case T4_RESOLUTION_R16_SUPERFINE:
1510 case T4_RESOLUTION_400_400:
1511 y_repeats = 4;
1512 break;
1513 case T4_RESOLUTION_400_800:
1514 y_repeats = 8;
1515 break;
1516 case T4_RESOLUTION_300_600:
1517 y_repeats = 6;
1518 break;
1519 case T4_RESOLUTION_600_600:
1520 y_repeats = 6;
1521 break;
1522 case T4_RESOLUTION_600_1200:
1523 y_repeats = 12;
1524 break;
1525 case T4_RESOLUTION_1200_1200:
1526 y_repeats = 12;
1527 break;
1528 }
1529 switch (s->metadata.width_code)
1530 {
1531 case T4_SUPPORT_WIDTH_215MM:
1532 break;
1533 case T4_SUPPORT_WIDTH_255MM:
1534 break;
1535 case T4_SUPPORT_WIDTH_303MM:
1536 break;
1537 }
1538 if (s->header_overlays_image)
1539 {
1540 /* Read and dump a row of the real image, allowing for the possibility
1541 that the real image might end within the header itself */
1542 if (len != s->row_handler(s->row_handler_user_data, buf, len))
1543 {
1544 set_row_read_handler(s, s->row_handler, s->row_handler_user_data);
1545 return len;
1546 }
1547 }
1548 t = s->header_text;
1549 row = s->header_row/y_repeats;
1550 pos = 0;
1551 switch (s->metadata.image_type)
1552 {
1553 case T4_IMAGE_TYPE_BILEVEL:
1554 for ( ; *t && pos <= len - 2; t++)
1555 {
1556 pattern = header_font[(uint8_t) *t][row];
1557 buf[pos++] = (uint8_t) (pattern >> 8);
1558 buf[pos++] = (uint8_t) (pattern & 0xFF);
1559 }
1560 if (pos < len)
1561 memset(&buf[pos], 0, len - pos);
1562 break;
1563 case T4_IMAGE_TYPE_GRAY_8BIT:
1564 for ( ; *t && pos <= len - 2; t++)
1565 {
1566 pattern = header_font[(uint8_t) *t][row];
1567 for (i = 0; i < 16; i++)
1568 {
1569 buf[pos + i] = (pattern & 0x8000) ? 0 : 0xFF;
1570 pattern <<= 1;
1571 }
1572 pos += 16;
1573 }
1574 if (pos < len)
1575 memset(&buf[pos], 0xFF, len - pos);
1576 break;
1577 case T4_IMAGE_TYPE_COLOUR_8BIT:
1578 for ( ; *t && pos <= len - 2; t++)
1579 {
1580 pattern = header_font[(uint8_t) *t][row];
1581 for (i = 0; i < 16; i++)
1582 {
1583 buf[pos + 3*i + 0] =
1584 buf[pos + 3*i + 1] =
1585 buf[pos + 3*i + 2] = (pattern & 0x8000) ? 0 : 0xFF;
1586 pattern <<= 1;
1587 }
1588 pos += 3*16;
1589 }
1590 if (pos < len)
1591 memset(&buf[pos], 0xFF, len - pos);
1592 break;
1593 case T4_IMAGE_TYPE_COLOUR_BILEVEL:
1594 case T4_IMAGE_TYPE_4COLOUR_BILEVEL:
1595 case T4_IMAGE_TYPE_GRAY_12BIT:
1596 case T4_IMAGE_TYPE_4COLOUR_8BIT:
1597 case T4_IMAGE_TYPE_COLOUR_12BIT:
1598 case T4_IMAGE_TYPE_4COLOUR_12BIT:
1599 default:
1600 memset(buf, 0xFF, len);
1601 }
1602 s->header_row++;
1603 if (s->header_row >= 16*y_repeats)
1604 {
1605 /* End of header. Change to normal image row data. */
1606 set_row_read_handler(s, s->row_handler, s->row_handler_user_data);
1607 }
1608 return len;
1609 }
1610 /*- End of function --------------------------------------------------------*/
1611
t4_tx_next_page_has_different_format(t4_tx_state_t * s)1612 SPAN_DECLARE(int) t4_tx_next_page_has_different_format(t4_tx_state_t *s)
1613 {
1614 span_log(&s->logging, SPAN_LOG_FLOW, "Checking for the existence of page %d\n", s->current_page + 1);
1615 if (s->current_page >= s->stop_page)
1616 return -1;
1617 if (s->tiff.file)
1618 {
1619 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page + 1))
1620 return -1;
1621 return test_tiff_directory_info(s);
1622 }
1623 return -1;
1624 }
1625 /*- End of function --------------------------------------------------------*/
1626
t4_tx_set_row_read_handler(t4_tx_state_t * s,t4_row_read_handler_t handler,void * user_data)1627 SPAN_DECLARE(int) t4_tx_set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler, void *user_data)
1628 {
1629 s->row_handler = handler;
1630 s->row_handler_user_data = user_data;
1631 return set_row_read_handler(s, handler, user_data);
1632 }
1633 /*- End of function --------------------------------------------------------*/
1634
release_encoder(t4_tx_state_t * s)1635 static int release_encoder(t4_tx_state_t *s)
1636 {
1637 switch (s->metadata.compression)
1638 {
1639 case T4_COMPRESSION_T4_1D:
1640 case T4_COMPRESSION_T4_2D:
1641 case T4_COMPRESSION_T6:
1642 return t4_t6_encode_release(&s->encoder.t4_t6);
1643 case T4_COMPRESSION_T85:
1644 case T4_COMPRESSION_T85_L0:
1645 return t85_encode_release(&s->encoder.t85);
1646 #if defined(SPANDSP_SUPPORT_T88)
1647 case T4_COMPRESSION_T88:
1648 return t88_encode_release(&s->encoder.t88);
1649 #endif
1650 case T4_COMPRESSION_T42_T81:
1651 case T4_COMPRESSION_SYCC_T81:
1652 return t42_encode_release(&s->encoder.t42);
1653 case T4_COMPRESSION_T43:
1654 return t43_encode_release(&s->encoder.t43);
1655 #if defined(SPANDSP_SUPPORT_T45)
1656 case T4_COMPRESSION_T45:
1657 return t45_encode_release(&s->encoder.t45);
1658 #endif
1659 }
1660 return -1;
1661 }
1662 /*- End of function --------------------------------------------------------*/
1663
t4_tx_set_tx_image_format(t4_tx_state_t * s,int supported_compressions,int supported_image_sizes,int supported_bilevel_resolutions,int supported_colour_resolutions)1664 SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
1665 int supported_compressions,
1666 int supported_image_sizes,
1667 int supported_bilevel_resolutions,
1668 int supported_colour_resolutions)
1669 {
1670 static const struct
1671 {
1672 int width;
1673 int width_code;
1674 int res_code; /* Correct resolution code */
1675 int alt_res_code; /* Fallback resolution code, where a metric/inch swap is possible */
1676 } width_and_res_info[] =
1677 {
1678 { T4_WIDTH_100_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_100_100, 0},
1679 { T4_WIDTH_100_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_100_100, 0},
1680 { T4_WIDTH_100_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_100_100, 0},
1681 { T4_WIDTH_200_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_200_100, T4_RESOLUTION_R8_STANDARD},
1682 { T4_WIDTH_200_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_200_200, T4_RESOLUTION_R8_FINE},
1683 { T4_WIDTH_200_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_200_400, T4_RESOLUTION_R8_SUPERFINE},
1684 { T4_WIDTH_200_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_R8_STANDARD, T4_RESOLUTION_200_100},
1685 { T4_WIDTH_200_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_R8_FINE, T4_RESOLUTION_200_200},
1686 { T4_WIDTH_200_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_R8_SUPERFINE, T4_RESOLUTION_200_400},
1687 { T4_WIDTH_200_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_200_100, T4_RESOLUTION_R8_STANDARD},
1688 { T4_WIDTH_200_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_200_200, T4_RESOLUTION_R8_FINE},
1689 { T4_WIDTH_200_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_200_400, T4_RESOLUTION_R8_SUPERFINE},
1690 { T4_WIDTH_200_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_R8_STANDARD, T4_RESOLUTION_200_100},
1691 { T4_WIDTH_200_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_R8_FINE, T4_RESOLUTION_200_200},
1692 { T4_WIDTH_200_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_R8_SUPERFINE, T4_RESOLUTION_200_400},
1693 { T4_WIDTH_200_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_200_100, T4_RESOLUTION_R8_STANDARD},
1694 { T4_WIDTH_200_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_200_200, T4_RESOLUTION_R8_FINE},
1695 { T4_WIDTH_200_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_200_400, T4_RESOLUTION_R8_SUPERFINE},
1696 { T4_WIDTH_200_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_R8_STANDARD, T4_RESOLUTION_200_100},
1697 { T4_WIDTH_200_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_R8_FINE, T4_RESOLUTION_200_200},
1698 { T4_WIDTH_200_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_R8_SUPERFINE, T4_RESOLUTION_200_400},
1699 { T4_WIDTH_300_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_300_300, 0},
1700 { T4_WIDTH_300_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_300_600, 0},
1701 { T4_WIDTH_300_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_300_300, 0},
1702 { T4_WIDTH_300_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_300_600, 0},
1703 { T4_WIDTH_400_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_400_400, T4_RESOLUTION_R16_SUPERFINE},
1704 { T4_WIDTH_400_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_400_800, 0},
1705 { T4_WIDTH_400_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_R16_SUPERFINE, T4_RESOLUTION_400_400},
1706 { T4_WIDTH_300_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_300_300, 0},
1707 { T4_WIDTH_300_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_300_600, 0},
1708 { T4_WIDTH_400_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_400_400, T4_RESOLUTION_R16_SUPERFINE},
1709 { T4_WIDTH_400_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_400_800, 0},
1710 { T4_WIDTH_400_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_R16_SUPERFINE, T4_RESOLUTION_400_400},
1711 { T4_WIDTH_400_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_400_400, T4_RESOLUTION_R16_SUPERFINE},
1712 { T4_WIDTH_400_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_400_800, 0},
1713 { T4_WIDTH_400_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_R16_SUPERFINE, T4_RESOLUTION_400_400},
1714 { T4_WIDTH_600_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_600_600, 0},
1715 { T4_WIDTH_600_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_600_1200, 0},
1716 { T4_WIDTH_600_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_600_600, 0},
1717 { T4_WIDTH_600_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_600_1200, 0},
1718 { T4_WIDTH_600_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_600_600, 0},
1719 { T4_WIDTH_600_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_600_1200, 0},
1720 {T4_WIDTH_1200_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_1200_1200, 0},
1721 {T4_WIDTH_1200_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_1200_1200, 0},
1722 {T4_WIDTH_1200_A3, T4_SUPPORT_WIDTH_303MM, T4_RESOLUTION_1200_1200, 0},
1723 {0x7FFFFFFF, -1, -1, -1}
1724 };
1725
1726 static const struct
1727 {
1728 int resolution;
1729 struct
1730 {
1731 int resolution;
1732 int squashing_factor;
1733 } fallback[4];
1734 } squashable[4] =
1735 {
1736 {
1737 T4_RESOLUTION_200_400,
1738 {
1739 {T4_RESOLUTION_200_200, 2},
1740 {T4_RESOLUTION_R8_FINE, 2},
1741 {T4_RESOLUTION_200_100, 4},
1742 {T4_RESOLUTION_R8_STANDARD, 4}
1743 }
1744 },
1745 {
1746 T4_RESOLUTION_200_200,
1747 {
1748 {T4_RESOLUTION_200_100, 2},
1749 {T4_RESOLUTION_R8_STANDARD, 2},
1750 {0, 0},
1751 {0, 0}
1752 }
1753 },
1754 {
1755 T4_RESOLUTION_R8_SUPERFINE,
1756 {
1757 {T4_RESOLUTION_R8_FINE, 2},
1758 {T4_RESOLUTION_200_200, 2},
1759 {T4_RESOLUTION_R8_STANDARD, 4},
1760 {T4_RESOLUTION_200_100, 4}
1761 }
1762 },
1763 {
1764 T4_RESOLUTION_R8_FINE,
1765 {
1766 {T4_RESOLUTION_R8_STANDARD, 2},
1767 {T4_RESOLUTION_200_100, 2},
1768 {0, 0},
1769 {0, 0}
1770 }
1771 }
1772 };
1773
1774 int i;
1775 int j;
1776 int entry;
1777 int compression;
1778 int res;
1779 int supported_colour_compressions;
1780
1781 supported_colour_compressions = supported_compressions & (T4_COMPRESSION_T42_T81 | T4_COMPRESSION_T43 | T4_COMPRESSION_T45 | T4_COMPRESSION_SYCC_T81);
1782 compression = -1;
1783 s->metadata.image_type = s->tiff.image_type;
1784 if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL)
1785 {
1786 span_log(&s->logging, SPAN_LOG_FLOW, "Non-bi-level image\n");
1787 /* Can we send this page as it is? */
1788 if (supported_colour_resolutions
1789 &&
1790 supported_colour_compressions
1791 &&
1792 (((s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
1793 &&
1794 (supported_compressions & T4_COMPRESSION_COLOUR))
1795 ||
1796 ((s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT || s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT)
1797 &&
1798 (supported_compressions & T4_COMPRESSION_GRAYSCALE))))
1799 {
1800 /* Gray-scale/colour is possible */
1801 span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is allowed\n");
1802 /* Choose the best gray-scale/colour encoding available to us */
1803 if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL && (supported_compressions & T4_COMPRESSION_T43))
1804 compression = T4_COMPRESSION_T43;
1805 else if ((supported_compressions & T4_COMPRESSION_T42_T81))
1806 compression = T4_COMPRESSION_T42_T81;
1807 else if ((supported_compressions & T4_COMPRESSION_T43))
1808 compression = T4_COMPRESSION_T43;
1809 else if ((supported_compressions & T4_COMPRESSION_T45))
1810 compression = T4_COMPRESSION_T45;
1811 else if ((supported_compressions & T4_COMPRESSION_SYCC_T81))
1812 compression = T4_COMPRESSION_SYCC_T81;
1813
1814 //best_colour_resolution(s->tiff.x_resolution, supported_colour_resolutions);
1815 }
1816 else
1817 {
1818 /* Gray-scale/colour is not possible. Can we flatten the image to send it? */
1819 span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is not allowed\n");
1820 switch (s->tiff.image_type)
1821 {
1822 case T4_IMAGE_TYPE_COLOUR_BILEVEL:
1823 case T4_IMAGE_TYPE_COLOUR_8BIT:
1824 case T4_IMAGE_TYPE_COLOUR_12BIT:
1825 if (!(supported_compressions & T4_COMPRESSION_COLOUR_TO_BILEVEL))
1826 {
1827 span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n");
1828 return T4_IMAGE_FORMAT_INCOMPATIBLE;
1829 }
1830 break;
1831 case T4_IMAGE_TYPE_GRAY_8BIT:
1832 case T4_IMAGE_TYPE_GRAY_12BIT:
1833 if (!(supported_compressions & T4_COMPRESSION_GRAY_TO_BILEVEL))
1834 {
1835 span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n");
1836 return T4_IMAGE_FORMAT_INCOMPATIBLE;
1837 }
1838 break;
1839 }
1840 /* Squashing to a bi-level image is possible */
1841 s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL;
1842 span_log(&s->logging, SPAN_LOG_FLOW, "The image will be flattened to %s\n", t4_image_type_to_str(s->metadata.image_type));
1843 }
1844 }
1845
1846 if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL)
1847 {
1848 /* Choose the best bi-level encoding available to us */
1849 if ((supported_compressions & T4_COMPRESSION_T85_L0))
1850 compression = T4_COMPRESSION_T85_L0;
1851 else if ((supported_compressions & T4_COMPRESSION_T85))
1852 compression = T4_COMPRESSION_T85;
1853 else if ((supported_compressions & T4_COMPRESSION_T6))
1854 compression = T4_COMPRESSION_T6;
1855 else if ((supported_compressions & T4_COMPRESSION_T4_2D))
1856 compression = T4_COMPRESSION_T4_2D;
1857 else
1858 compression = T4_COMPRESSION_T4_1D;
1859 }
1860
1861 /* Deal with the image width/resolution combination. */
1862 /* Look for a pattern that matches the image */
1863 s->metadata.width_code = -1;
1864 for (entry = 0; s->tiff.image_width >= width_and_res_info[entry].width; entry++)
1865 {
1866 if (s->tiff.image_width == width_and_res_info[entry].width && s->tiff.resolution_code == width_and_res_info[entry].res_code)
1867 {
1868 s->metadata.width_code = width_and_res_info[entry].width_code;
1869 break;
1870 }
1871 }
1872 s->row_squashing_ratio = 1;
1873 if (s->metadata.width_code >= 0 && (supported_image_sizes & s->metadata.width_code))
1874 {
1875 /* We have a valid and supported width/resolution combination */
1876
1877 /* No resize necessary */
1878 s->metadata.image_width = s->tiff.image_width;
1879 s->metadata.image_length = s->tiff.image_length;
1880
1881 res = T4_IMAGE_FORMAT_NORESSUPPORT;
1882 if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL)
1883 {
1884 if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions))
1885 {
1886 /* We can use the resolution of the original image */
1887 s->metadata.resolution_code = s->tiff.resolution_code;
1888 s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
1889 s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
1890 res = T4_IMAGE_FORMAT_OK;
1891 }
1892 else if ((width_and_res_info[entry].alt_res_code & supported_bilevel_resolutions))
1893 {
1894 /* We can do a metric/imperial swap, and have a usable resolution */
1895 span_log(&s->logging,
1896 SPAN_LOG_FLOW,
1897 "Image resolution %s falls back to %s\n",
1898 t4_image_resolution_to_str(s->tiff.resolution_code),
1899 t4_image_resolution_to_str(width_and_res_info[entry].alt_res_code));
1900 s->metadata.resolution_code = width_and_res_info[entry].alt_res_code;
1901 s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
1902 s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
1903 res = T4_IMAGE_FORMAT_OK;
1904 }
1905 else
1906 {
1907 if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL)
1908 {
1909 if ((s->tiff.resolution_code & (T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE)))
1910 {
1911 /* This might be a resolution we can squash down to something which is supported */
1912 for (i = 0; i < 4; i++)
1913 {
1914 if ((s->tiff.resolution_code & squashable[i].resolution))
1915 break;
1916 }
1917 if (i < 4)
1918 {
1919 /* This is a squashable resolution, so let's see if there is a valid
1920 fallback we can squash the image to, scanning through the entries
1921 in their order of preference. */
1922 for (j = 0; j < 4; j++)
1923 {
1924 if ((supported_bilevel_resolutions & squashable[i].fallback[j].resolution))
1925 {
1926 span_log(&s->logging,
1927 SPAN_LOG_FLOW,
1928 "Image resolution %s falls back to %s\n",
1929 t4_image_resolution_to_str(s->tiff.resolution_code),
1930 t4_image_resolution_to_str(squashable[i].fallback[j].resolution));
1931 s->row_squashing_ratio = squashable[i].fallback[j].squashing_factor;
1932 s->metadata.resolution_code = squashable[i].fallback[j].resolution;
1933 s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
1934 s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
1935 res = T4_IMAGE_FORMAT_OK;
1936 break;
1937 }
1938 }
1939 }
1940 }
1941 }
1942 }
1943 /* If we have not succeeded in matching up the size and resolution, the next step will
1944 depend on whether the original was a bi-level image. If it was, we are stuck, as you can't
1945 really resize those. If it was not, a resize might be possible */
1946 if (res != T4_IMAGE_FORMAT_OK)
1947 {
1948 if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL)
1949 return T4_IMAGE_FORMAT_NORESSUPPORT;
1950 if (!(supported_compressions & T4_COMPRESSION_RESCALING))
1951 return T4_IMAGE_FORMAT_NOSIZESUPPORT;
1952 }
1953 /* TODO */
1954 }
1955 else
1956 {
1957 if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions))
1958 {
1959 if ((s->tiff.resolution_code & supported_colour_resolutions))
1960 {
1961 /* We can use the resolution of the original image */
1962 s->metadata.resolution_code = width_and_res_info[entry].res_code;
1963 s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
1964 s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
1965 res = T4_IMAGE_FORMAT_OK;
1966 }
1967 }
1968 }
1969 }
1970 else
1971 {
1972 /* Can we rework the image to fit? */
1973 /* We can't rework a bilevel image that fits none of the patterns */
1974 if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL)
1975 return T4_IMAGE_FORMAT_NORESSUPPORT;
1976 if (!(supported_compressions & T4_COMPRESSION_RESCALING))
1977 return T4_IMAGE_FORMAT_NOSIZESUPPORT;
1978 /* Any other kind of image might be resizable */
1979 res = T4_IMAGE_FORMAT_OK;
1980 /* TODO: use more sophisticated resizing */
1981 s->metadata.image_width = T4_WIDTH_200_A4;
1982 s->metadata.resolution_code = T4_RESOLUTION_200_200;
1983 s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
1984 s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
1985 }
1986
1987 if (res != T4_IMAGE_FORMAT_OK)
1988 return res;
1989
1990 if (s->metadata.image_type != s->tiff.image_type || s->metadata.image_width != s->tiff.image_width)
1991 {
1992 if (image_translate_init(&s->translator,
1993 s->metadata.image_type,
1994 s->metadata.image_width,
1995 -1,
1996 s->tiff.image_type,
1997 s->tiff.image_width,
1998 s->tiff.image_length,
1999 translate_row_read2,
2000 s) == NULL)
2001 {
2002 return T4_IMAGE_FORMAT_INCOMPATIBLE;
2003 }
2004 s->metadata.image_length = image_translate_get_output_length(&s->translator);
2005 }
2006
2007 if (compression != s->metadata.compression)
2008 {
2009 switch (compression)
2010 {
2011 case T4_COMPRESSION_T4_1D:
2012 case T4_COMPRESSION_T4_2D:
2013 case T4_COMPRESSION_T6:
2014 switch (s->metadata.compression)
2015 {
2016 case T4_COMPRESSION_T4_1D:
2017 case T4_COMPRESSION_T4_2D:
2018 case T4_COMPRESSION_T6:
2019 break;
2020 default:
2021 release_encoder(s);
2022 t4_t6_encode_init(&s->encoder.t4_t6, compression, s->metadata.image_width, s->metadata.image_length, s->row_handler, s->row_handler_user_data);
2023 break;
2024 }
2025 s->metadata.compression = compression;
2026 res = T4_IMAGE_FORMAT_OK;
2027 if (t4_t6_encode_set_encoding(&s->encoder.t4_t6, compression))
2028 res = -1;
2029 break;
2030 case T4_COMPRESSION_T85:
2031 case T4_COMPRESSION_T85_L0:
2032 switch (s->metadata.compression)
2033 {
2034 case T4_COMPRESSION_T85:
2035 case T4_COMPRESSION_T85_L0:
2036 break;
2037 default:
2038 release_encoder(s);
2039 t85_encode_init(&s->encoder.t85, s->metadata.image_width, s->metadata.image_length, s->row_handler, s->row_handler_user_data);
2040 break;
2041 }
2042 s->metadata.compression = compression;
2043 res = T4_IMAGE_FORMAT_OK;
2044 break;
2045 #if defined(SPANDSP_SUPPORT_T88)
2046 case T4_COMPRESSION_T88:
2047 switch (s->metadata.compression)
2048 {
2049 case T4_COMPRESSION_T88:
2050 break;
2051 default:
2052 t88_encode_init(&s->encoder.t88, s->metadata.image_width, s->metadata.image_length, s->row_handler, s->row_handler_user_data);
2053 break;
2054 }
2055 s->metadata.compression = compression;
2056 res = T4_IMAGE_FORMAT_OK;
2057 break;
2058 #endif
2059 case T4_COMPRESSION_T42_T81:
2060 case T4_COMPRESSION_SYCC_T81:
2061 switch (s->metadata.compression)
2062 {
2063 case T4_COMPRESSION_T42_T81:
2064 case T4_COMPRESSION_SYCC_T81:
2065 break;
2066 default:
2067 release_encoder(s);
2068 t42_encode_init(&s->encoder.t42, s->metadata.image_width, s->metadata.image_length, s->row_handler, s->row_handler_user_data);
2069 break;
2070 }
2071 s->metadata.compression = compression;
2072 res = T4_IMAGE_FORMAT_OK;
2073 break;
2074 case T4_COMPRESSION_T43:
2075 switch (s->metadata.compression)
2076 {
2077 case T4_COMPRESSION_T43:
2078 break;
2079 default:
2080 release_encoder(s);
2081 t43_encode_init(&s->encoder.t43, s->metadata.image_width, s->metadata.image_length, s->row_handler, s->row_handler_user_data);
2082 break;
2083 }
2084 s->metadata.compression = compression;
2085 res = T4_IMAGE_FORMAT_OK;
2086 break;
2087 #if defined(SPANDSP_SUPPORT_T45)
2088 case T4_COMPRESSION_T45:
2089 switch (s->metadata.compression)
2090 {
2091 case T4_COMPRESSION_T45:
2092 break;
2093 default:
2094 release_encoder(s);
2095 t45_encode_init(&s->encoder.t45, s->metadata.image_width, s->metadata.image_length, s->row_handler, s->row_handler_user_data);
2096 break;
2097 }
2098 s->metadata.compression = compression;
2099 res = T4_IMAGE_FORMAT_OK;
2100 break;
2101 #endif
2102 }
2103 }
2104
2105 switch (s->metadata.compression)
2106 {
2107 case T4_COMPRESSION_T4_1D:
2108 case T4_COMPRESSION_T4_2D:
2109 case T4_COMPRESSION_T6:
2110 t4_t6_encode_set_max_2d_rows_per_1d_row(&s->encoder.t4_t6, -s->metadata.y_resolution);
2111 break;
2112 }
2113
2114 set_image_width(s, s->metadata.image_width);
2115 set_image_length(s, s->metadata.image_length);
2116 t4_tx_set_image_type(s, s->metadata.image_type);
2117 return res;
2118 }
2119 /*- End of function --------------------------------------------------------*/
2120
t4_tx_get_tx_compression(t4_tx_state_t * s)2121 SPAN_DECLARE(int) t4_tx_get_tx_compression(t4_tx_state_t *s)
2122 {
2123 return s->metadata.compression;
2124 }
2125 /*- End of function --------------------------------------------------------*/
2126
t4_tx_get_tx_image_type(t4_tx_state_t * s)2127 SPAN_DECLARE(int) t4_tx_get_tx_image_type(t4_tx_state_t *s)
2128 {
2129 return s->metadata.image_type;
2130 }
2131 /*- End of function --------------------------------------------------------*/
2132
t4_tx_get_tx_resolution(t4_tx_state_t * s)2133 SPAN_DECLARE(int) t4_tx_get_tx_resolution(t4_tx_state_t *s)
2134 {
2135 return s->metadata.resolution_code;
2136 }
2137 /*- End of function --------------------------------------------------------*/
2138
t4_tx_get_tx_x_resolution(t4_tx_state_t * s)2139 SPAN_DECLARE(int) t4_tx_get_tx_x_resolution(t4_tx_state_t *s)
2140 {
2141 return s->metadata.x_resolution;
2142 }
2143 /*- End of function --------------------------------------------------------*/
2144
t4_tx_get_tx_y_resolution(t4_tx_state_t * s)2145 SPAN_DECLARE(int) t4_tx_get_tx_y_resolution(t4_tx_state_t *s)
2146 {
2147 return s->metadata.y_resolution;
2148 }
2149 /*- End of function --------------------------------------------------------*/
2150
t4_tx_get_tx_image_width(t4_tx_state_t * s)2151 SPAN_DECLARE(int) t4_tx_get_tx_image_width(t4_tx_state_t *s)
2152 {
2153 return s->metadata.image_width;
2154 }
2155 /*- End of function --------------------------------------------------------*/
2156
t4_tx_get_tx_image_width_code(t4_tx_state_t * s)2157 SPAN_DECLARE(int) t4_tx_get_tx_image_width_code(t4_tx_state_t *s)
2158 {
2159 return s->metadata.width_code;
2160 }
2161 /*- End of function --------------------------------------------------------*/
2162
set_image_width(t4_tx_state_t * s,uint32_t image_width)2163 static void set_image_width(t4_tx_state_t *s, uint32_t image_width)
2164 {
2165 s->metadata.image_width = image_width;
2166 switch (s->metadata.compression)
2167 {
2168 case T4_COMPRESSION_T4_1D:
2169 case T4_COMPRESSION_T4_2D:
2170 case T4_COMPRESSION_T6:
2171 t4_t6_encode_set_image_width(&s->encoder.t4_t6, image_width);
2172 break;
2173 case T4_COMPRESSION_T85:
2174 case T4_COMPRESSION_T85_L0:
2175 t85_encode_set_image_width(&s->encoder.t85, image_width);
2176 break;
2177 #if defined(SPANDSP_SUPPORT_T88)
2178 case T4_COMPRESSION_T88:
2179 t88_encode_set_image_width(&s->encoder.t88, image_width);
2180 break;
2181 #endif
2182 case T4_COMPRESSION_T42_T81:
2183 case T4_COMPRESSION_SYCC_T81:
2184 t42_encode_set_image_width(&s->encoder.t42, image_width);
2185 break;
2186 case T4_COMPRESSION_T43:
2187 t43_encode_set_image_width(&s->encoder.t43, image_width);
2188 break;
2189 #if defined(SPANDSP_SUPPORT_T45)
2190 case T4_COMPRESSION_T45:
2191 t45_encode_set_image_width(&s->encoder.t45, image_width);
2192 break;
2193 #endif
2194 }
2195 }
2196 /*- End of function --------------------------------------------------------*/
2197
set_image_length(t4_tx_state_t * s,uint32_t image_length)2198 static void set_image_length(t4_tx_state_t *s, uint32_t image_length)
2199 {
2200 s->metadata.image_length = image_length;
2201 switch (s->metadata.compression)
2202 {
2203 case T4_COMPRESSION_T4_1D:
2204 case T4_COMPRESSION_T4_2D:
2205 case T4_COMPRESSION_T6:
2206 t4_t6_encode_set_image_length(&s->encoder.t4_t6, image_length);
2207 break;
2208 case T4_COMPRESSION_T85:
2209 case T4_COMPRESSION_T85_L0:
2210 t85_encode_set_image_length(&s->encoder.t85, image_length);
2211 break;
2212 #if defined(SPANDSP_SUPPORT_T88)
2213 case T4_COMPRESSION_T88:
2214 t88_encode_set_image_length(&s->encoder.t88, image_length);
2215 break;
2216 #endif
2217 case T4_COMPRESSION_T42_T81:
2218 case T4_COMPRESSION_SYCC_T81:
2219 t42_encode_set_image_length(&s->encoder.t42, image_length);
2220 break;
2221 case T4_COMPRESSION_T43:
2222 t43_encode_set_image_length(&s->encoder.t43, image_length);
2223 break;
2224 #if defined(SPANDSP_SUPPORT_T45)
2225 case T4_COMPRESSION_T45:
2226 t45_encode_set_image_length(&s->encoder.t45, image_length);
2227 break;
2228 #endif
2229 }
2230 }
2231 /*- End of function --------------------------------------------------------*/
2232
t4_tx_set_image_type(t4_tx_state_t * s,int image_type)2233 static void t4_tx_set_image_type(t4_tx_state_t *s, int image_type)
2234 {
2235 s->metadata.image_type = image_type;
2236 switch (s->metadata.compression)
2237 {
2238 #if defined(SPANDSP_SUPPORT_T88)
2239 case T4_COMPRESSION_T88:
2240 t88_encode_set_image_type(&s->encoder.t88, image_type);
2241 break;
2242 #endif
2243 case T4_COMPRESSION_T42_T81:
2244 case T4_COMPRESSION_SYCC_T81:
2245 t42_encode_set_image_type(&s->encoder.t42, image_type);
2246 break;
2247 case T4_COMPRESSION_T43:
2248 t43_encode_set_image_type(&s->encoder.t43, image_type);
2249 break;
2250 #if defined(SPANDSP_SUPPORT_T45)
2251 case T4_COMPRESSION_T45:
2252 t45_encode_set_image_type(&s->encoder.t45, image_type);
2253 break;
2254 #endif
2255 }
2256 }
2257 /*- End of function --------------------------------------------------------*/
2258
t4_tx_set_min_bits_per_row(t4_tx_state_t * s,int bits)2259 SPAN_DECLARE(void) t4_tx_set_min_bits_per_row(t4_tx_state_t *s, int bits)
2260 {
2261 switch (s->metadata.compression)
2262 {
2263 case T4_COMPRESSION_T4_1D:
2264 case T4_COMPRESSION_T4_2D:
2265 case T4_COMPRESSION_T6:
2266 t4_t6_encode_set_min_bits_per_row(&s->encoder.t4_t6, bits);
2267 break;
2268 }
2269 }
2270 /*- End of function --------------------------------------------------------*/
2271
t4_tx_set_max_2d_rows_per_1d_row(t4_tx_state_t * s,int max)2272 SPAN_DECLARE(void) t4_tx_set_max_2d_rows_per_1d_row(t4_tx_state_t *s, int max)
2273 {
2274 switch (s->metadata.compression)
2275 {
2276 case T4_COMPRESSION_T4_1D:
2277 case T4_COMPRESSION_T4_2D:
2278 case T4_COMPRESSION_T6:
2279 t4_t6_encode_set_max_2d_rows_per_1d_row(&s->encoder.t4_t6, max);
2280 break;
2281 }
2282 }
2283 /*- End of function --------------------------------------------------------*/
2284
t4_tx_set_header_overlays_image(t4_tx_state_t * s,bool header_overlays_image)2285 SPAN_DECLARE(void) t4_tx_set_header_overlays_image(t4_tx_state_t *s, bool header_overlays_image)
2286 {
2287 s->header_overlays_image = header_overlays_image;
2288 }
2289 /*- End of function --------------------------------------------------------*/
2290
t4_tx_set_local_ident(t4_tx_state_t * s,const char * ident)2291 SPAN_DECLARE(void) t4_tx_set_local_ident(t4_tx_state_t *s, const char *ident)
2292 {
2293 s->local_ident = (ident && ident[0]) ? ident : NULL;
2294 }
2295 /*- End of function --------------------------------------------------------*/
2296
t4_tx_set_header_info(t4_tx_state_t * s,const char * info)2297 SPAN_DECLARE(void) t4_tx_set_header_info(t4_tx_state_t *s, const char *info)
2298 {
2299 s->header_info = (info && info[0]) ? info : NULL;
2300 }
2301 /*- End of function --------------------------------------------------------*/
2302
t4_tx_set_header_tz(t4_tx_state_t * s,struct tz_s * tz)2303 SPAN_DECLARE(void) t4_tx_set_header_tz(t4_tx_state_t *s, struct tz_s *tz)
2304 {
2305 s->tz = tz;
2306 }
2307 /*- End of function --------------------------------------------------------*/
2308
t4_tx_get_pages_in_file(t4_tx_state_t * s)2309 SPAN_DECLARE(int) t4_tx_get_pages_in_file(t4_tx_state_t *s)
2310 {
2311 int max;
2312
2313 if (s->tiff.file)
2314 max = get_tiff_total_pages(s);
2315 else
2316 max = 1;
2317 if (max >= 0)
2318 s->tiff.pages_in_file = max;
2319 return max;
2320 }
2321 /*- End of function --------------------------------------------------------*/
2322
t4_tx_get_current_page_in_file(t4_tx_state_t * s)2323 SPAN_DECLARE(int) t4_tx_get_current_page_in_file(t4_tx_state_t *s)
2324 {
2325 return s->current_page;
2326 }
2327 /*- End of function --------------------------------------------------------*/
2328
t4_tx_get_transfer_statistics(t4_tx_state_t * s,t4_stats_t * t)2329 SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t)
2330 {
2331 memset(t, 0, sizeof(*t));
2332 t->pages_transferred = s->current_page - s->start_page;
2333 t->pages_in_file = s->tiff.pages_in_file;
2334
2335 t->image_type = s->tiff.image_type;
2336 t->image_width = s->tiff.image_width;
2337 t->image_length = s->tiff.image_length;
2338
2339 t->image_x_resolution = s->tiff.x_resolution;
2340 t->image_y_resolution = s->tiff.y_resolution;
2341 t->x_resolution = s->metadata.x_resolution;
2342 t->y_resolution = s->metadata.y_resolution;
2343
2344 t->type = s->metadata.image_type;
2345 t->compression = s->metadata.compression;
2346
2347 switch (s->metadata.compression)
2348 {
2349 case T4_COMPRESSION_T4_1D:
2350 case T4_COMPRESSION_T4_2D:
2351 case T4_COMPRESSION_T6:
2352 t->width = t4_t6_encode_get_image_width(&s->encoder.t4_t6);
2353 t->length = t4_t6_encode_get_image_length(&s->encoder.t4_t6);
2354 t->line_image_size = t4_t6_encode_get_compressed_image_size(&s->encoder.t4_t6)/8;
2355 break;
2356 case T4_COMPRESSION_T85:
2357 case T4_COMPRESSION_T85_L0:
2358 t->width = t85_encode_get_image_width(&s->encoder.t85);
2359 t->length = t85_encode_get_image_length(&s->encoder.t85);
2360 t->line_image_size = t85_encode_get_compressed_image_size(&s->encoder.t85)/8;
2361 break;
2362 #if defined(SPANDSP_SUPPORT_T88)
2363 case T4_COMPRESSION_T88:
2364 t->width = t88_encode_get_image_width(&s->encoder.t88);
2365 t->length = t88_encode_get_image_length(&s->encoder.t88);
2366 t->line_image_size = t88_encode_get_compressed_image_size(&s->encoder.t88)/8;
2367 break;
2368 #endif
2369 case T4_COMPRESSION_T42_T81:
2370 case T4_COMPRESSION_SYCC_T81:
2371 t->width = t42_encode_get_image_width(&s->encoder.t42);
2372 t->length = t42_encode_get_image_length(&s->encoder.t42);
2373 t->line_image_size = t42_encode_get_compressed_image_size(&s->encoder.t42)/8;
2374 break;
2375 case T4_COMPRESSION_T43:
2376 t->width = t43_encode_get_image_width(&s->encoder.t43);
2377 t->length = t43_encode_get_image_length(&s->encoder.t43);
2378 t->line_image_size = t43_encode_get_compressed_image_size(&s->encoder.t43)/8;
2379 break;
2380 #if defined(SPANDSP_SUPPORT_T45)
2381 case T4_COMPRESSION_T45:
2382 t->width = t45_encode_get_image_width(&s->encoder.t45);
2383 t->length = t45_encode_get_image_length(&s->encoder.t45);
2384 t->line_image_size = t45_encode_get_compressed_image_size(&s->encoder.t45)/8;
2385 break;
2386 #endif
2387 }
2388 }
2389 /*- End of function --------------------------------------------------------*/
2390
t4_tx_image_complete(t4_tx_state_t * s)2391 SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s)
2392 {
2393 if (s->no_encoder.buf_len > 0)
2394 {
2395 if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len)
2396 return SIG_STATUS_END_OF_DATA;
2397 return 0;
2398 }
2399
2400 switch (s->metadata.compression)
2401 {
2402 case T4_COMPRESSION_T4_1D:
2403 case T4_COMPRESSION_T4_2D:
2404 case T4_COMPRESSION_T6:
2405 return t4_t6_encode_image_complete(&s->encoder.t4_t6);
2406 case T4_COMPRESSION_T85:
2407 case T4_COMPRESSION_T85_L0:
2408 return t85_encode_image_complete(&s->encoder.t85);
2409 #if defined(SPANDSP_SUPPORT_T88)
2410 case T4_COMPRESSION_T88:
2411 return t88_encode_image_complete(&s->encoder.t88);
2412 #endif
2413 case T4_COMPRESSION_T42_T81:
2414 case T4_COMPRESSION_SYCC_T81:
2415 return t42_encode_image_complete(&s->encoder.t42);
2416 case T4_COMPRESSION_T43:
2417 return t43_encode_image_complete(&s->encoder.t43);
2418 #if defined(SPANDSP_SUPPORT_T45)
2419 case T4_COMPRESSION_T45:
2420 return t45_encode_image_complete(&s->encoder.t45);
2421 #endif
2422 }
2423 return SIG_STATUS_END_OF_DATA;
2424 }
2425 /*- End of function --------------------------------------------------------*/
2426
t4_tx_get_bit(t4_tx_state_t * s)2427 SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s)
2428 {
2429 int bit;
2430
2431 /* We only get bit by bit for T.4 1D and T.4 2-D. */
2432 if (s->no_encoder.buf_len > 0)
2433 {
2434 if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len)
2435 return SIG_STATUS_END_OF_DATA;
2436 bit = (s->no_encoder.buf[s->no_encoder.buf_ptr] >> s->no_encoder.bit) & 1;
2437 if (++s->no_encoder.bit >= 8)
2438 {
2439 s->no_encoder.bit = 0;
2440 s->no_encoder.buf_ptr++;
2441 }
2442 return bit;
2443 }
2444 return t4_t6_encode_get_bit(&s->encoder.t4_t6);
2445 }
2446 /*- End of function --------------------------------------------------------*/
2447
t4_tx_get(t4_tx_state_t * s,uint8_t buf[],size_t max_len)2448 SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len)
2449 {
2450 if (s->no_encoder.buf_len > 0)
2451 {
2452 if (max_len > (s->no_encoder.buf_len - s->no_encoder.buf_ptr))
2453 max_len = s->no_encoder.buf_len - s->no_encoder.buf_ptr;
2454 memcpy(buf, &s->no_encoder.buf[s->no_encoder.buf_ptr], max_len);
2455 s->no_encoder.buf_ptr += max_len;
2456 return max_len;
2457 }
2458
2459 if (s->image_get_handler)
2460 return s->image_get_handler((void *) &s->encoder, buf, max_len);
2461
2462 return 0;
2463 }
2464 /*- End of function --------------------------------------------------------*/
2465
t4_tx_start_page(t4_tx_state_t * s)2466 SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s)
2467 {
2468 span_log(&s->logging, SPAN_LOG_FLOW, "Start tx page %d - compression %s\n", s->current_page, t4_compression_to_str(s->metadata.compression));
2469 if (s->current_page > s->stop_page)
2470 return -1;
2471 if (s->tiff.file)
2472 {
2473 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page))
2474 return -1;
2475 get_tiff_directory_info(s);
2476 if (read_tiff_image(s) < 0)
2477 return -1;
2478 }
2479 else
2480 {
2481 s->metadata.image_length = UINT32_MAX;
2482 }
2483
2484 switch (s->metadata.compression)
2485 {
2486 case T4_COMPRESSION_T4_1D:
2487 case T4_COMPRESSION_T4_2D:
2488 case T4_COMPRESSION_T6:
2489 t4_t6_encode_restart(&s->encoder.t4_t6, s->metadata.image_width, s->metadata.image_length);
2490 s->image_get_handler = (t4_image_get_handler_t) t4_t6_encode_get;
2491 break;
2492 case T4_COMPRESSION_T85:
2493 case T4_COMPRESSION_T85_L0:
2494 t85_encode_restart(&s->encoder.t85, s->metadata.image_width, s->metadata.image_length);
2495 s->image_get_handler = (t4_image_get_handler_t) t85_encode_get;
2496 break;
2497 #if defined(SPANDSP_SUPPORT_T88)
2498 case T4_COMPRESSION_T88:
2499 t88_encode_restart(&s->encoder.t88, s->metadata.image_width, s->metadata.image_length);
2500 s->image_get_handler = (t4_image_get_handler_t) t88_encode_get;
2501 break;
2502 #endif
2503 case T4_COMPRESSION_T42_T81:
2504 case T4_COMPRESSION_SYCC_T81:
2505 t42_encode_restart(&s->encoder.t42, s->metadata.image_width, s->metadata.image_length);
2506 s->image_get_handler = (t4_image_get_handler_t) t42_encode_get;
2507 break;
2508 case T4_COMPRESSION_T43:
2509 t43_encode_restart(&s->encoder.t43, s->metadata.image_width, s->metadata.image_length);
2510 s->image_get_handler = (t4_image_get_handler_t) t43_encode_get;
2511 break;
2512 #if defined(SPANDSP_SUPPORT_T45)
2513 case T4_COMPRESSION_T45:
2514 t45_encode_restart(&s->encoder.t45, s->metadata.image_width, s->metadata.image_length);
2515 s->image_get_handler = (t4_image_get_handler_t) t45_encode_get;
2516 break;
2517 #endif
2518 default:
2519 s->image_get_handler = NULL;
2520 break;
2521 }
2522
2523 /* If there is a page header, create that first */
2524 //if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL && s->header_info && s->header_info[0] && make_header(s) == 0)
2525 if (s->header_info && s->header_info[0] && make_header(s) == 0)
2526 {
2527 s->header_row = 0;
2528 set_row_read_handler(s, header_row_read_handler, (void *) s);
2529 }
2530 else
2531 {
2532 set_row_read_handler(s, s->row_handler, s->row_handler_user_data);
2533 }
2534 return 0;
2535 }
2536 /*- End of function --------------------------------------------------------*/
2537
t4_tx_restart_page(t4_tx_state_t * s)2538 SPAN_DECLARE(int) t4_tx_restart_page(t4_tx_state_t *s)
2539 {
2540 /* This is currently the same as starting a page, but keep it a separate call,
2541 as the two things might diverge a little in the future. */
2542 return t4_tx_start_page(s);
2543 }
2544 /*- End of function --------------------------------------------------------*/
2545
t4_tx_end_page(t4_tx_state_t * s)2546 SPAN_DECLARE(int) t4_tx_end_page(t4_tx_state_t *s)
2547 {
2548 s->current_page++;
2549 return 0;
2550 }
2551 /*- End of function --------------------------------------------------------*/
2552
t4_tx_get_logging_state(t4_tx_state_t * s)2553 SPAN_DECLARE(logging_state_t *) t4_tx_get_logging_state(t4_tx_state_t *s)
2554 {
2555 return &s->logging;
2556 }
2557 /*- End of function --------------------------------------------------------*/
2558
t4_tx_init(t4_tx_state_t * s,const char * file,int start_page,int stop_page)2559 SPAN_DECLARE(t4_tx_state_t *) t4_tx_init(t4_tx_state_t *s, const char *file, int start_page, int stop_page)
2560 {
2561 int allocated;
2562
2563 allocated = false;
2564 if (s == NULL)
2565 {
2566 if ((s = (t4_tx_state_t *) span_alloc(sizeof(*s))) == NULL)
2567 return NULL;
2568 allocated = true;
2569 }
2570 memset(s, 0, sizeof(*s));
2571 #if defined(SPANDSP_SUPPORT_TIFF_FX)
2572 TIFF_FX_init();
2573 #endif
2574 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
2575 span_log_set_protocol(&s->logging, "T.4");
2576
2577 span_log(&s->logging, SPAN_LOG_FLOW, "Start tx document\n");
2578
2579 s->current_page =
2580 s->start_page = (start_page >= 0) ? start_page : 0;
2581 s->stop_page = (stop_page >= 0) ? stop_page : INT_MAX;
2582 s->metadata.compression = T4_COMPRESSION_NONE;
2583
2584 s->row_handler = tiff_row_read_handler;
2585 s->row_handler_user_data = (void *) s;
2586
2587 s->row_squashing_ratio = 1;
2588
2589 if (file)
2590 {
2591 if (open_tiff_input_file(s, file) < 0)
2592 {
2593 if (allocated)
2594 span_free(s);
2595 return NULL;
2596 }
2597 s->tiff.file = strdup(file);
2598 s->tiff.pages_in_file = -1;
2599 if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page)
2600 ||
2601 get_tiff_directory_info(s))
2602 {
2603 tiff_tx_release(s);
2604 if (allocated)
2605 span_free(s);
2606 return NULL;
2607 }
2608 }
2609 return s;
2610 }
2611 /*- End of function --------------------------------------------------------*/
2612
t4_tx_release(t4_tx_state_t * s)2613 SPAN_DECLARE(int) t4_tx_release(t4_tx_state_t *s)
2614 {
2615 if (s->tiff.file)
2616 tiff_tx_release(s);
2617 if (s->header_text)
2618 {
2619 span_free(s->header_text);
2620 s->header_text = NULL;
2621 }
2622 if (s->colour_map)
2623 {
2624 span_free(s->colour_map);
2625 s->colour_map = NULL;
2626 }
2627 return release_encoder(s);
2628 }
2629 /*- End of function --------------------------------------------------------*/
2630
t4_tx_free(t4_tx_state_t * s)2631 SPAN_DECLARE(int) t4_tx_free(t4_tx_state_t *s)
2632 {
2633 int ret;
2634
2635 ret = t4_tx_release(s);
2636 span_free(s);
2637 return ret;
2638 }
2639 /*- End of function --------------------------------------------------------*/
2640 /*- End of file ------------------------------------------------------------*/
2641