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