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