Bug Summary

File:src/t42.c
Warning:line 390, column 9
Function call argument is an uninitialized value

Annotated Source Code

1/*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * t42.c - ITU T.42 JPEG for FAX image processing
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2011 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 <stdlib.h>
33#include <inttypes.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#include <float.h>
42#if defined(HAVE_TGMATH_H1)
43#include <tgmath.h>
44#endif
45#if defined(HAVE_MATH_H1)
46#include <math.h>
47#endif
48#if defined(HAVE_STDBOOL_H1)
49#include <stdbool.h>
50#else
51#include "spandsp/stdbool.h"
52#endif
53#include "floating_fudge.h"
54#include <tiffio.h>
55#include <assert.h>
56
57#include "spandsp/telephony.h"
58#include "spandsp/alloc.h"
59#include "spandsp/unaligned.h"
60#include "spandsp/fast_convert.h"
61#include "spandsp/logging.h"
62#include "spandsp/saturated.h"
63#include "spandsp/async.h"
64#include "spandsp/timezone.h"
65#include "spandsp/t4_rx.h"
66#include "spandsp/t4_tx.h"
67#include "spandsp/t81_t82_arith_coding.h"
68#include "spandsp/t85.h"
69#include "spandsp/t42.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
76/* The open_memstream() and fmemopen() in older versions of glibc seem quirky */
77#if defined(__GLIBC__2) && (__GLIBC__2 < 2 || (__GLIBC__2 == 2 && __GLIBC_MINOR__24 < 12))
78#undef OPEN_MEMSTREAM
79#endif
80
81#define T42_USE_LUTS
82
83#include "t42_t43_local.h"
84#if defined(T42_USE_LUTS)
85#include "cielab_luts.h"
86#endif
87
88typedef struct
89{
90 float L;
91 float a;
92 float b;
93} cielab_t;
94
95typedef struct
96{
97 uint8_t tag[5];
98 const char *name;
99 float xn;
100 float yn;
101 float zn;
102} illuminant_t;
103
104static const illuminant_t illuminants[] =
105{
106 {"\0D50", "CIE D50/2°", 96.422f, 100.000f, 82.521f}, /* Horizon Light. ICC profile PCS */
107 {"", "CIE D50/10°", 96.720f, 100.000f, 81.427f},
108 {"", "CIE D55/2°", 95.682f, 100.000f, 92.149f}, /* Mid-morning/mid-afternoon daylight */
109 {"", "CIE D55/10°", 95.799f, 100.000f, 90.926f},
110 {"\0D65", "CIE D65/2°", 95.047f, 100.000f, 108.883f}, /* Noon daylight, television, sRGB color space */
111 {"", "CIE D65/10°", 94.811f, 100.000f, 107.304f},
112 {"\0D75", "CIE D75/2°", 94.972f, 100.000f, 122.638f}, /* North sky daylight */
113 {"", "CIE D75/10°", 94.416f, 100.000f, 120.641f},
114 {"\0\0F2", "F02/2°", 99.186f, 100.000f, 67.393f}, /* Cool white fluorescent */
115 {"", "F02/10°", 103.279f, 100.000f, 69.027f},
116 {"\0\0F7", "F07/2°", 95.041f, 100.000f, 108.747f}, /* D65 simulator, daylight simulator */
117 {"", "F07/10°", 95.792f, 100.000f, 107.686f},
118 {"\0F11", "F11/2°", 100.962f, 100.000f, 64.350f}, /* Philips TL84, Ultralume 40 */
119 {"", "F11/10°", 103.863f, 100.000f, 65.607f},
120 {"\0\0SA", "A/2°", 109.850f, 100.000f, 35.585f}, /* Incandescent/tungsten */
121 {"", "A/10°", 111.144f, 100.000f, 35.200f},
122 {"\0\0SC", "C/2°", 98.074f, 100.000f, 118.232f}, /* {obsolete} average/north sky daylight */
123 {"", "C/10°", 97.285f, 100.000f, 116.145f},
124 {"", "", 0.000f, 0.000f, 0.000f}
125};
126
127/* LERP(a,b,c) = linear interpolation macro, is 'a' when c == 0.0 and 'b' when c == 1.0 */
128#define LERP(a,b,c)(((b) - (a))*(c) + (a)) (((b) - (a))*(c) + (a))
129
130typedef struct UVT
131{
132 double u;
133 double v;
134 double t;
135} UVT;
136
137static const double rt[31] =
138{
139 /* Reciprocal temperature (K) */
140 FLT_MIN1.17549435e-38F,
141 10.0e-6,
142 20.0e-6,
143 30.0e-6,
144 40.0e-6,
145 50.0e-6,
146 60.0e-6,
147 70.0e-6,
148 80.0e-6,
149 90.0e-6,
150 100.0e-6,
151 125.0e-6,
152 150.0e-6,
153 175.0e-6,
154 200.0e-6,
155 225.0e-6,
156 250.0e-6,
157 275.0e-6,
158 300.0e-6,
159 325.0e-6,
160 350.0e-6,
161 375.0e-6,
162 400.0e-6,
163 425.0e-6,
164 450.0e-6,
165 475.0e-6,
166 500.0e-6,
167 525.0e-6,
168 550.0e-6,
169 575.0e-6,
170 600.0e-6
171};
172
173static const UVT uvt[31] =
174{
175 {0.18006, 0.26352, -0.24341},
176 {0.18066, 0.26589, -0.25479},
177 {0.18133, 0.26846, -0.26876},
178 {0.18208, 0.27119, -0.28539},
179 {0.18293, 0.27407, -0.30470},
180 {0.18388, 0.27709, -0.32675},
181 {0.18494, 0.28021, -0.35156},
182 {0.18611, 0.28342, -0.37915},
183 {0.18740, 0.28668, -0.40955},
184 {0.18880, 0.28997, -0.44278},
185 {0.19032, 0.29326, -0.47888},
186 {0.19462, 0.30141, -0.58204},
187 {0.19962, 0.30921, -0.70471},
188 {0.20525, 0.31647, -0.84901},
189 {0.21142, 0.32312, -1.01820},
190 {0.21807, 0.32909, -1.21680},
191 {0.22511, 0.33439, -1.45120},
192 {0.23247, 0.33904, -1.72980},
193 {0.24010, 0.34308, -2.06370},
194 {0.24792, 0.34655, -2.46810}, /* Note: 0.24792 is a corrected value for the error found in W&S as 0.24702 */
195 {0.25591, 0.34951, -2.96410},
196 {0.26400, 0.35200, -3.58140},
197 {0.27218, 0.35407, -4.36330},
198 {0.28039, 0.35577, -5.37620},
199 {0.28863, 0.35714, -6.72620},
200 {0.29685, 0.35823, -8.59550},
201 {0.30505, 0.35907, -11.3240},
202 {0.31320, 0.35968, -15.6280},
203 {0.32129, 0.36011, -23.3250},
204 {0.32931, 0.36038, -40.7700},
205 {0.33724, 0.36051, -116.450}
206};
207
208SPAN_DECLARE(bool)__attribute__((visibility("default"))) _Bool t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len)
209{
210 int type;
211 int seg;
212 int pos;
213
214 /* Search the image data for its width and length */
215 *length = 0;
216 *width = 0;
217
218 pos = 0;
219 if (get_net_unaligned_uint16(&data[pos]) != 0xFFD8)
220 return false0;
221 /*endif*/
222 pos += 2;
223 while (pos < len)
224 {
225 type = get_net_unaligned_uint16(&data[pos]);
226 pos += 2;
227 seg = get_net_unaligned_uint16(&data[pos]) - 2;
228 pos += 2;
229 if (type == 0xFFC0)
230 {
231 *length = get_net_unaligned_uint16(&data[pos + 1]);
232 *width = get_net_unaligned_uint16(&data[pos + 3]);
233 return true1;
234 }
235 /*endif*/
236 pos += seg;
237 }
238 /*endwhile*/
239 return false0;
240}
241/*- End of function --------------------------------------------------------*/
242
243SPAN_DECLARE(int)__attribute__((visibility("default"))) int xyz_to_corrected_color_temp(float *temp, float xyz[3])
244{
245 float us;
246 float vs;
247 float p;
248 float di;
249 float dm;
250 int i;
251
252 /* Protect against possible divide-by-zero failure */
253 if ((xyz[0] < 1.0e-20f) && (xyz[1] < 1.0e-20f) && (xyz[2] < 1.0e-20f))
254 return -1;
255 /*endif*/
256 us = (4.0f*xyz[0])/(xyz[0] + 15.0f*xyz[1] + 3.0f*xyz[2]);
257 vs = (6.0f*xyz[1])/(xyz[0] + 15.0f*xyz[1] + 3.0f*xyz[2]);
258 dm = 0.0f;
259 for (i = 0; i < 31; i++)
260 {
261 di = (vs - uvt[i].v) - uvt[i].t*(us - uvt[i].u);
262 if ((i > 0) && (((di < 0.0f) && (dm >= 0.0f)) || ((di >= 0.0f) && (dm < 0.0f))))
263 break; /* found lines bounding (us, vs) : i-1 and i */
264 /*endif*/
265 dm = di;
266 }
267 /*endfor*/
268 if (i == 31)
269 {
270 /* Bad XYZ input, color temp would be less than minimum of 1666.7 degrees, or too far towards blue */
271 return -1;
272 }
273 /*endif*/
274 di = di/sqrtf(1.0f + uvt[i ].t*uvt[i ].t);
275 dm = dm/sqrtf(1.0f + uvt[i - 1].t*uvt[i - 1].t);
276 p = dm/(dm - di); /* p = interpolation parameter, 0.0 : i-1, 1.0 : i */
277 p = 1.0f/(LERP(rt[i - 1], rt[i], p)(((rt[i]) - (rt[i - 1]))*(p) + (rt[i - 1])));
278 *temp = p;
279 return 0;
280}
281/*- End of function --------------------------------------------------------*/
282
283SPAN_DECLARE(int)__attribute__((visibility("default"))) int colour_temp_to_xyz(float xyz[3], float temp)
284{
285 float x;
286 float y;
287
288 /* Should be good for 1667K to 25000K according to Wikipedia */
289 if (temp < 1667.0f || temp > 25000.0f)
290 return -1;
291
292 if (temp < 4000.0f)
293 x = -0.2661239e9f/(temp*temp*temp) - 0.2343580e6f/(temp*temp) + 0.8776956e3f/temp + 0.179910f;
294 else
295 x = -3.0258469e9f/(temp*temp*temp) + 2.1070379e6f/(temp*temp) + 0.2226347e3f/temp + 0.240390f;
296 /*endif*/
297
298 if (temp < 2222.0f)
299 y = -1.1063814f*x*x*x - 1.34811020f*x*x + 2.18555832f*x - 0.20219683f;
300 else if (temp < 4000.0f)
301 y = -0.9549476f*x*x*x - 1.37418593f*x*x + 2.09137015f*x - 0.16748867f;
302 else
303 y = 3.0817580f*x*x*x - 5.87338670f*x*x + 3.75112997f*x - 0.37001483f;
304 /*endif*/
305
306 xyz[0] = x/y;
307 xyz[1] = 1.0f;
308 xyz[2] = (1.0f - x - y)/y;
309
310 return 0;
311}
312/*- End of function --------------------------------------------------------*/
313
314SPAN_DECLARE(void)__attribute__((visibility("default"))) void set_lab_illuminant(lab_params_t *lab, float new_xn, float new_yn, float new_zn)
315{
316 if (new_yn > 10.0f)
317 {
318 lab->x_n = new_xn/100.0f;
319 lab->y_n = new_yn/100.0f;
320 lab->z_n = new_zn/100.0f;
321 }
322 else
323 {
324 lab->x_n = new_xn;
325 lab->y_n = new_yn;
326 lab->z_n = new_zn;
327 }
328 /*endif*/
329 lab->x_rn = 1.0f/lab->x_n;
330 lab->y_rn = 1.0f/lab->y_n;
331 lab->z_rn = 1.0f/lab->z_n;
332}
333/*- End of function --------------------------------------------------------*/
334
335SPAN_DECLARE(void)__attribute__((visibility("default"))) void set_lab_gamut(lab_params_t *lab, int L_min, int L_max, int a_min, int a_max, int b_min, int b_max, int ab_are_signed)
336{
337 lab->range_L = L_max - L_min;
338 lab->range_a = a_max - a_min;
339 lab->range_b = b_max - b_min;
340
341 lab->offset_L = -256.0f*L_min/lab->range_L;
342 lab->offset_a = -256.0f*a_min/lab->range_a;
343 lab->offset_b = -256.0f*b_min/lab->range_b;
344
345 lab->range_L /= (256.0f - 1.0f);
346 lab->range_a /= (256.0f - 1.0f);
347 lab->range_b /= (256.0f - 1.0f);
348
349 lab->ab_are_signed = ab_are_signed;
350}
351/*- End of function --------------------------------------------------------*/
352
353SPAN_DECLARE(void)__attribute__((visibility("default"))) void set_lab_gamut2(lab_params_t *lab, int L_P, int L_Q, int a_P, int a_Q, int b_P, int b_Q)
354{
355 lab->range_L = L_Q/(256.0f - 1.0f);
356 lab->range_a = a_Q/(256.0f - 1.0f);
357 lab->range_b = b_Q/(256.0f - 1.0f);
358
359 lab->offset_L = L_P;
360 lab->offset_a = a_P;
361 lab->offset_b = b_P;
362
363 lab->ab_are_signed = false0;
364}
365/*- End of function --------------------------------------------------------*/
366
367SPAN_DECLARE(void)__attribute__((visibility("default"))) void get_lab_gamut2(lab_params_t *lab, int *L_P, int *L_Q, int *a_P, int *a_Q, int *b_P, int *b_Q)
368{
369 *L_Q = lab->range_L*(256.0f - 1.0f);
370 *a_Q = lab->range_a*(256.0f - 1.0f);
371 *b_Q = lab->range_b*(256.0f - 1.0f);
372
373 *L_P = lab->offset_L;
374 *a_P = lab->offset_a;
375 *b_P = lab->offset_b;
376}
377/*- End of function --------------------------------------------------------*/
378
379int set_illuminant_from_code(logging_state_t *logging, lab_params_t *lab, const uint8_t code[4])
380{
381 int i;
382 int colour_temp;
383 float xyz[3];
384
385 if (memcmp(code, "CT", 2) == 0)
12
Taking true branch
386 {
387 colour_temp = get_net_unaligned_uint16(&code[2]);
388 span_log(logging, SPAN_LOG_FLOW, "Illuminant colour temp %dK\n", colour_temp);
389 colour_temp_to_xyz(xyz, (float) colour_temp);
390 set_lab_illuminant(lab, xyz[0], xyz[1], xyz[2]);
13
Function call argument is an uninitialized value
391 return colour_temp;
392 }
393 /*endif*/
394 for (i = 0; illuminants[i].name[0]; i++)
395 {
396 if (memcmp(code, illuminants[i].tag, 4) == 0)
397 {
398 span_log(logging, SPAN_LOG_FLOW, "Illuminant %s\n", illuminants[i].name);
399 set_lab_illuminant(lab, illuminants[i].xn, illuminants[i].yn, illuminants[i].zn);
400 return 0;
401 }
402 /*endif*/
403 }
404 /*endfor*/
405 if (illuminants[i].name[0] == '\0')
406 span_log(logging, SPAN_LOG_FLOW, "Unrecognised illuminant 0x%x 0x%x 0x%x 0x%x\n", code[0], code[1], code[2], code[3]);
407 /*endif*/
408 return -1;
409}
410/*- End of function --------------------------------------------------------*/
411
412void set_gamut_from_code(logging_state_t *logging, lab_params_t *s, const uint8_t code[12])
413{
414 int i;
415 int val[6];
416
417 for (i = 0; i < 6; i++)
418 val[i] = get_net_unaligned_uint16(&code[2*i]);
419 /*endfor*/
420 span_log(logging,
421 SPAN_LOG_FLOW,
422 "Gamut L=[%d,%d], a*=[%d,%d], b*=[%d,%d]\n",
423 val[0],
424 val[1],
425 val[2],
426 val[3],
427 val[4],
428 val[5]);
429 set_lab_gamut2(s, val[0], val[1], val[2], val[3], val[4], val[5]);
430}
431/*- End of function --------------------------------------------------------*/
432
433static __inline__ void itu_to_lab(lab_params_t *s, cielab_t *lab, const uint8_t in[3])
434{
435 uint8_t a;
436 uint8_t b;
437
438 /* T.4 E.6.4 */
439 lab->L = s->range_L*(in[0] - s->offset_L);
440 a = in[1];
441 b = in[2];
442 if (s->ab_are_signed)
443 {
444 a += 128;
445 b += 128;
446 }
447 /*endif*/
448 lab->a = s->range_a*(a - s->offset_a);
449 lab->b = s->range_b*(b - s->offset_b);
450}
451/*- End of function --------------------------------------------------------*/
452
453static __inline__ void lab_to_itu(lab_params_t *s, uint8_t out[3], const cielab_t *lab)
454{
455 /* T.4 E.6.4 */
456 out[0] = saturateu8(floorf(lab->L/s->range_L + s->offset_L));
457 out[1] = saturateu8(floorf(lab->a/s->range_a + s->offset_a));
458 out[2] = saturateu8(floorf(lab->b/s->range_b + s->offset_b));
459 if (s->ab_are_signed)
460 {
461 out[1] -= 128;
462 out[2] -= 128;
463 }
464 /*endif*/
465}
466/*- End of function --------------------------------------------------------*/
467
468SPAN_DECLARE(void)__attribute__((visibility("default"))) void srgb_to_lab(lab_params_t *s, uint8_t lab[], const uint8_t srgb[], int pixels)
469{
470 float x;
471 float y;
472 float z;
473 float r;
474 float g;
475 float b;
476 float xx;
477 float yy;
478 float zz;
479 cielab_t l;
480 int i;
481
482 for (i = 0; i < 3*pixels; i += 3)
483 {
484#if defined(T42_USE_LUTS)
485 r = srgb_to_linear[srgb[i]];
486 g = srgb_to_linear[srgb[i + 1]];
487 b = srgb_to_linear[srgb[i + 2]];
488#else
489 r = srgb[i]/256.0f;
490 g = srgb[i + 1]/256.0f;
491 b = srgb[i + 2]/256.0f;
492
493 /* sRGB to linear RGB */
494 r = (r > 0.04045f) ? powf((r + 0.055f)/1.055f, 2.4f) : r/12.92f;
495 g = (g > 0.04045f) ? powf((g + 0.055f)/1.055f, 2.4f) : g/12.92f;
496 b = (b > 0.04045f) ? powf((b + 0.055f)/1.055f, 2.4f) : b/12.92f;
497#endif
498
499 /* Linear RGB to XYZ */
500 x = 0.4124f*r + 0.3576f*g + 0.1805f*b;
501 y = 0.2126f*r + 0.7152f*g + 0.0722f*b;
502 z = 0.0193f*r + 0.1192f*g + 0.9505f*b;
503
504 /* Normalise for the illuminant */
505 x *= s->x_rn;
506 y *= s->y_rn;
507 z *= s->z_rn;
508
509 /* XYZ to Lab */
510 xx = (x <= 0.008856f) ? (7.787f*x + 0.1379f) : cbrtf(x);
511 yy = (y <= 0.008856f) ? (7.787f*y + 0.1379f) : cbrtf(y);
512 zz = (z <= 0.008856f) ? (7.787f*z + 0.1379f) : cbrtf(z);
513 l.L = 116.0f*yy - 16.0f;
514 l.a = 500.0f*(xx - yy);
515 l.b = 200.0f*(yy - zz);
516
517 lab_to_itu(s, lab, &l);
518
519 lab += 3;
520 }
521 /*endfor*/
522}
523/*- End of function --------------------------------------------------------*/
524
525SPAN_DECLARE(void)__attribute__((visibility("default"))) void lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t lab[], int pixels)
526{
527 float x;
528 float y;
529 float z;
530 float r;
531 float g;
532 float b;
533 float ll;
534 cielab_t l;
535 int val;
536 int i;
537
538 for (i = 0; i < 3*pixels; i += 3)
539 {
540 itu_to_lab(s, &l, lab);
541
542 /* Lab to XYZ */
543 ll = (1.0f/116.0f)*(l.L + 16.0f);
544 y = ll;
545 y = (y <= 0.2068f) ? (0.1284f*(y - 0.1379f)) : y*y*y;
546 x = ll + (1.0f/500.0f)*l.a;
547 x = (x <= 0.2068f) ? (0.1284f*(x - 0.1379f)) : x*x*x;
548 z = ll - (1.0f/200.0f)*l.b;
549 z = (z <= 0.2068f) ? (0.1284f*(z - 0.1379f)) : z*z*z;
550
551 /* Normalise for the illuminant */
552 x *= s->x_n;
553 y *= s->y_n;
554 z *= s->z_n;
555
556 /* XYZ to linear RGB */
557 r = 3.2406f*x - 1.5372f*y - 0.4986f*z;
558 g = -0.9689f*x + 1.8758f*y + 0.0415f*z;
559 b = 0.0557f*x - 0.2040f*y + 1.0570f*z;
560
561#if defined(T42_USE_LUTS)
562 val = r*4096.0f;
563 srgb[i] = linear_to_srgb[(val < 0) ? 0 : (val < 4095) ? val : 4095];
564 val = g*4096.0f;
565 srgb[i + 1] = linear_to_srgb[(val < 0) ? 0 : (val < 4095) ? val : 4095];
566 val = b*4096.0f;
567 srgb[i + 2] = linear_to_srgb[(val < 0) ? 0 : (val < 4095) ? val : 4095];
568#else
569 /* Linear RGB to sRGB */
570 r = (r > 0.0031308f) ? (1.055f*powf(r, 1.0f/2.4f) - 0.055f) : r*12.92f;
571 g = (g > 0.0031308f) ? (1.055f*powf(g, 1.0f/2.4f) - 0.055f) : g*12.92f;
572 b = (b > 0.0031308f) ? (1.055f*powf(b, 1.0f/2.4f) - 0.055f) : b*12.92f;
573
574 srgb[i] = saturateu8(floorf(r*256.0f));
575 srgb[i + 1] = saturateu8(floorf(g*256.0f));
576 srgb[i + 2] = saturateu8(floorf(b*256.0f));
577#endif
578 lab += 3;
579 }
580 /*endfor*/
581}
582/*- End of function --------------------------------------------------------*/
583
584static int is_itu_fax(t42_decode_state_t *s, jpeg_saved_marker_ptr ptr)
585{
586 const uint8_t *data;
587 int ok;
588 int val[6];
589
590 ok = false0;
591 for ( ; ptr; ptr = ptr->next)
1
Loop condition is true. Entering loop body
592 {
593 if (ptr->marker != (JPEG_APP00xE0 + 1))
2
Assuming the condition is false
3
Taking false branch
594 continue;
595 /*endif*/
596 if (ptr->data_length < 6)
4
Assuming the condition is false
5
Taking false branch
597 return false0;
598 /*endif*/
599 /* Markers are:
600 JPEG_RST0
601 JPEG_EOI
602 JPEG_APP0
603 JPEG_COM */
604 data = (const uint8_t *) ptr->data;
605 if (strncmp((const char *) data, "G3FAX", 5))
6
Assuming the condition is false
7
Taking false branch
606 return false0;
607 /*endif*/
608 switch (data[5])
8
Control jumps to 'case 2:' at line 632
609 {
610 case 0:
611 if (ptr->data_length < 6 + 4)
612 {
613 span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX0 length - %d\n", ptr->data_length);
614 return false0;
615 }
616 /*endif*/
617 val[0] = get_net_unaligned_uint16(&data[6]);
618 s->spatial_resolution = get_net_unaligned_uint16(&data[6 + 2]);
619 span_log(&s->logging, SPAN_LOG_FLOW, "Version %d, resolution %ddpi\n", val[0], s->spatial_resolution);
620 ok = true1;
621 break;
622 case 1:
623 span_log(&s->logging, SPAN_LOG_FLOW, "Set gamut\n");
624 if (ptr->data_length < 6 + 12)
625 {
626 span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX1 length - %d\n", ptr->data_length);
627 return false0;
628 }
629 /*endif*/
630 set_gamut_from_code(&s->logging, &s->lab, &data[6]);
631 break;
632 case 2:
633 span_log(&s->logging, SPAN_LOG_FLOW, "Set illuminant\n");
634 if (ptr->data_length < 6 + 4)
9
Assuming the condition is false
10
Taking false branch
635 {
636 span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX2 length - %d\n", ptr->data_length);
637 return false0;
638 }
639 /*endif*/
640 s->illuminant_colour_temperature = set_illuminant_from_code(&s->logging, &s->lab, &data[6]);
11
Calling 'set_illuminant_from_code'
641 break;
642 default:
643 span_log(&s->logging, SPAN_LOG_FLOW, "Got unexpected G3FAX%d length - %d\n", data[5], ptr->data_length);
644 return false0;
645 }
646 /*endswitch*/
647 }
648 /*endfor*/
649
650 return ok;
651}
652/*- End of function --------------------------------------------------------*/
653
654static void set_itu_fax(t42_encode_state_t *s)
655{
656 uint8_t data[50];
657 int val[6];
658
659 memcpy(data, "G3FAX\0", 6);
660 put_net_unaligned_uint16(&data[6 + 0], 1994);
661 put_net_unaligned_uint16(&data[6 + 2], s->spatial_resolution);
662 jpeg_write_marker(&s->compressor, (JPEG_APP00xE0 + 1), data, 6 + 4);
663
664 if (s->lab.offset_L != 0
665 ||
666 s->lab.range_L != 100
667 ||
668 s->lab.offset_a != 128
669 ||
670 s->lab.range_a != 170
671 ||
672 s->lab.offset_b != 96
673 ||
674 s->lab.range_b != 200)
675 {
676 span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX1\n");
677 memcpy(data, "G3FAX\1", 6);
678 get_lab_gamut2(&s->lab, &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]);
679 put_net_unaligned_uint16(&data[6 + 0], val[0]);
680 put_net_unaligned_uint16(&data[6 + 2], val[1]);
681 put_net_unaligned_uint16(&data[6 + 4], val[2]);
682 put_net_unaligned_uint16(&data[6 + 6], val[3]);
683 put_net_unaligned_uint16(&data[6 + 8], val[4]);
684 put_net_unaligned_uint16(&data[6 + 10], val[5]);
685 jpeg_write_marker(&s->compressor, (JPEG_APP00xE0 + 1), data, 6 + 12);
686 }
687 /*endif*/
688
689 if (memcmp(s->illuminant_code, "\0\0\0\0", 4) != 0
690 ||
691 s->illuminant_colour_temperature > 0)
692 {
693 span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX2\n");
694 memcpy(data, "G3FAX\2", 6);
695 if (memcmp(s->illuminant_code, "\0\0\0\0", 4) != 0)
696 {
697 memcpy(&data[6], s->illuminant_code, 4);
698 }
699 else
700 {
701 memcpy(&data[6 + 0], "CT", 2);
702 put_net_unaligned_uint16(&data[6 + 2], s->illuminant_colour_temperature);
703 }
704 /*endif*/
705 jpeg_write_marker(&s->compressor, (JPEG_APP00xE0 + 1), data, 6 + 4);
706 }
707 /*endif*/
708}
709/*- End of function --------------------------------------------------------*/
710
711SPAN_DECLARE(void)__attribute__((visibility("default"))) void t42_encode_set_options(t42_encode_state_t *s,
712 uint32_t l0,
713 int quality,
714 int options)
715{
716 s->quality = quality;
717 s->no_subsampling = (options & 1);
718}
719/*- End of function --------------------------------------------------------*/
720
721SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width)
722{
723 s->image_width = image_width;
724 return 0;
725}
726/*- End of function --------------------------------------------------------*/
727
728SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_set_image_length(t42_encode_state_t *s, uint32_t image_length)
729{
730 s->image_length = image_length;
731 return 0;
732}
733/*- End of function --------------------------------------------------------*/
734
735SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_set_image_type(t42_encode_state_t *s, int image_type)
736{
737 s->image_type = image_type;
738 return 0;
739}
740/*- End of function --------------------------------------------------------*/
741
742SPAN_DECLARE(void)__attribute__((visibility("default"))) void t42_encode_abort(t42_encode_state_t *s)
743{
744}
745/*- End of function --------------------------------------------------------*/
746
747SPAN_DECLARE(void)__attribute__((visibility("default"))) void t42_encode_comment(t42_encode_state_t *s, const uint8_t comment[], size_t len)
748{
749}
750/*- End of function --------------------------------------------------------*/
751
752SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_image_complete(t42_encode_state_t *s)
753{
754 //if (????)
755 // return SIG_STATUS_END_OF_DATA;
756 /*endif*/
757 return 0;
758}
759/*- End of function --------------------------------------------------------*/
760
761/* Error handler for IJG library */
762static void jpg_encode_error_exit(j_common_ptr cinfo)
763{
764 t42_encode_state_t *s;
765
766 s = (t42_encode_state_t *) cinfo->client_data;
767 (*cinfo->err->format_message)(cinfo, s->error_message);
768 longjmp(s->escape, 1);
769}
770/*- End of function --------------------------------------------------------*/
771
772/* This is the error catcher */
773static struct jpeg_error_mgr encode_error_handler =
774{
775#if defined(_MSC_VER) || defined(__sunos) || defined(__solaris) || defined(__sun)
776 jpg_encode_error_exit,
777 0,
778 jpg_encode_error_exit
779#else
780 .error_exit = jpg_encode_error_exit,
781 .output_message = jpg_encode_error_exit
782#endif
783};
784
785static int t42_srgb_to_itulab_jpeg(t42_encode_state_t *s)
786{
787 int i;
788
789 if (setjmp(s->escape)_setjmp (s->escape))
790 {
791 if (s->error_message[0])
792 span_log(&s->logging, SPAN_LOG_FLOW, "%s\n", s->error_message);
793 else
794 span_log(&s->logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n");
795 /*endif*/
796 if (s->scan_line_out)
797 {
798 span_free(s->scan_line_out);
799 s->scan_line_out = NULL((void*)0);
800 }
801 /*endif*/
802 if (s->out)
803 {
804 fclose(s->out);
805 s->out = NULL((void*)0);
806 }
807 /*endif*/
808 return -1;
809 }
810 /*endif*/
811
812 s->compressor.err = jpeg_std_error(&encode_error_handler);
813 s->compressor.client_data = (void *) s;
814
815 jpeg_create_compress(&s->compressor)jpeg_CreateCompress((&s->compressor), 62, (size_t) sizeof
(struct jpeg_compress_struct))
;
816 jpeg_stdio_dest(&s->compressor, s->out);
817
818 /* Force the destination colour space */
819 if (s->image_type == T4_IMAGE_TYPE_COLOUR_8BIT)
820 {
821 s->samples_per_pixel = 3;
822 s->compressor.in_color_space = JCS_YCbCr;
823 s->compressor.input_components = s->samples_per_pixel;
824 }
825 else
826 {
827 s->samples_per_pixel = 1;
828 s->compressor.in_color_space = JCS_GRAYSCALE;
829 s->compressor.input_components = s->samples_per_pixel;
830 }
831 /*endif*/
832
833 jpeg_set_defaults(&s->compressor);
834 /* Limit to baseline-JPEG values */
835 //jpeg_set_quality(&s->compressor, s->quality, true);
836
837 if (s->no_subsampling)
838 {
839 /* Set 1:1:1 */
840 s->compressor.comp_info[0].h_samp_factor = 1;
841 s->compressor.comp_info[0].v_samp_factor = 1;
842 }
843 else
844 {
845 /* Set 4:1:1 */
846 s->compressor.comp_info[0].h_samp_factor = 2;
847 s->compressor.comp_info[0].v_samp_factor = 2;
848 }
849 /*endif*/
850 s->compressor.comp_info[1].h_samp_factor = 1;
851 s->compressor.comp_info[1].v_samp_factor = 1;
852 s->compressor.comp_info[2].h_samp_factor = 1;
853 s->compressor.comp_info[2].v_samp_factor = 1;
854
855 /* Size, resolution, etc */
856 s->compressor.image_width = s->image_width;
857 s->compressor.image_height = s->image_length;
858
859 jpeg_start_compress(&s->compressor, true1);
860
861 set_itu_fax(s);
862
863 if ((s->scan_line_in = (JSAMPROW) span_alloc(s->samples_per_pixel*s->image_width)) == NULL((void*)0))
864 return -1;
865 /*endif*/
866
867 if (s->image_type == T4_IMAGE_TYPE_COLOUR_8BIT)
868 {
869 if ((s->scan_line_out = (JSAMPROW) span_alloc(s->samples_per_pixel*s->image_width)) == NULL((void*)0))
870 return -1;
871 /*endif*/
872
873 for (i = 0; i < s->compressor.image_height; i++)
874 {
875 s->row_read_handler(s->row_read_user_data, s->scan_line_in, s->samples_per_pixel*s->image_width);
876 srgb_to_lab(&s->lab, s->scan_line_out, s->scan_line_in, s->image_width);
877 jpeg_write_scanlines(&s->compressor, &s->scan_line_out, 1);
878 }
879 /*endfor*/
880 }
881 else
882 {
883 for (i = 0; i < s->compressor.image_height; i++)
884 {
885 s->row_read_handler(s->row_read_user_data, s->scan_line_in, s->image_width);
886 jpeg_write_scanlines(&s->compressor, &s->scan_line_in, 1);
887 }
888 /*endfor*/
889 }
890 /*endif*/
891
892 if (s->scan_line_out)
893 {
894 span_free(s->scan_line_out);
895 s->scan_line_out = NULL((void*)0);
896 }
897 /*endif*/
898 jpeg_finish_compress(&s->compressor);
899 jpeg_destroy_compress(&s->compressor);
900
901#if defined(HAVE_OPEN_MEMSTREAM1)
902 fclose(s->out);
903 s->buf_size =
904 s->compressed_image_size = s->outsize;
905#else
906 s->buf_size =
907 s->compressed_image_size = ftell(s->out);
908 if ((s->compressed_buf = span_alloc(s->compressed_image_size)) == NULL((void*)0))
909 return -1;
910 /*endif*/
911 if (fseek(s->out, 0, SEEK_SET0) != 0)
912 {
913 fclose(s->out);
914 s->out = NULL((void*)0);
915 span_free(s->compressed_buf);
916 s->compressed_buf = NULL((void*)0);
917 return -1;
918 }
919 /*endif*/
920 if (fread(s->compressed_buf, 1, s->compressed_image_size, s->out) != s->compressed_image_size)
921 {
922 fclose(s->out);
923 s->out = NULL((void*)0);
924 span_free(s->compressed_buf);
925 s->compressed_buf = NULL((void*)0);
926 return -1;
927 }
928 /*endif*/
929 if (s->out)
930 {
931 fclose(s->out);
932 s->out = NULL((void*)0);
933 }
934 /*endif*/
935#endif
936
937 return 0;
938}
939/*- End of function --------------------------------------------------------*/
940
941SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_get(t42_encode_state_t *s, uint8_t buf[], size_t max_len)
942{
943 int len;
944
945 if (s->compressed_image_size == 0)
946 {
947 if (t42_srgb_to_itulab_jpeg(s))
948 {
949 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to convert to ITULAB.\n");
950 return -1;
951 }
952 /*endif*/
953 }
954 /*endif*/
955 if (s->compressed_image_size >= s->compressed_image_ptr + max_len)
956 len = max_len;
957 else
958 len = s->compressed_image_size - s->compressed_image_ptr;
959 /*endif*/
960 memcpy(buf, &s->compressed_buf[s->compressed_image_ptr], len);
961 s->compressed_image_ptr += len;
962 return len;
963}
964/*- End of function --------------------------------------------------------*/
965
966SPAN_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t t42_encode_get_image_width(t42_encode_state_t *s)
967{
968 return s->image_width;
969}
970/*- End of function --------------------------------------------------------*/
971
972SPAN_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t t42_encode_get_image_length(t42_encode_state_t *s)
973{
974 return s->image_length;
975}
976/*- End of function --------------------------------------------------------*/
977
978SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_get_compressed_image_size(t42_encode_state_t *s)
979{
980 return s->compressed_image_size;
981}
982/*- End of function --------------------------------------------------------*/
983
984SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_set_row_read_handler(t42_encode_state_t *s,
985 t4_row_read_handler_t handler,
986 void *user_data)
987{
988 s->row_read_handler = handler;
989 s->row_read_user_data = user_data;
990 return 0;
991}
992/*- End of function --------------------------------------------------------*/
993
994SPAN_DECLARE(logging_state_t *)__attribute__((visibility("default"))) logging_state_t * t42_encode_get_logging_state(t42_encode_state_t *s)
995{
996 return &s->logging;
997}
998/*- End of function --------------------------------------------------------*/
999
1000SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_restart(t42_encode_state_t *s, uint32_t image_width, uint32_t image_length)
1001{
1002 s->image_width = image_width;
1003 s->image_length = image_length;
1004
1005 if (s->itu_ycc)
1006 {
1007 /* ITU-YCC */
1008 /* Illuminant D65 */
1009 //set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
1010 set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
1011 set_lab_gamut(&s->lab, 0, 100, -127, 127, -127, 127, false0);
1012 }
1013 else
1014 {
1015 /* ITULAB */
1016 /* Illuminant D50 */
1017 //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
1018 set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
1019 set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false0);
1020 }
1021 s->compressed_image_size = 0;
1022 s->compressed_image_ptr = 0;
1023
1024 s->spatial_resolution = 200;
1025
1026 s->error_message[0] = '\0';
1027
1028#if defined(HAVE_OPEN_MEMSTREAM1)
1029 s->outsize = 0;
1030 if ((s->out = open_memstream((char **) &s->compressed_buf, &s->outsize)) == NULL((void*)0))
1031 {
1032 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
1033 return -1;
1034 }
1035 /*endif*/
1036#else
1037 if ((s->out = tmpfile()) == NULL((void*)0))
1038 {
1039 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
1040 return -1;
1041 /*endif*/
1042 }
1043 /*endif*/
1044#endif
1045 s->scan_line_out = NULL((void*)0);
1046
1047 return 0;
1048}
1049/*- End of function --------------------------------------------------------*/
1050
1051SPAN_DECLARE(t42_encode_state_t *)__attribute__((visibility("default"))) t42_encode_state_t * t42_encode_init(t42_encode_state_t *s,
1052 uint32_t image_width,
1053 uint32_t image_length,
1054 t4_row_read_handler_t handler,
1055 void *user_data)
1056{
1057 if (s == NULL((void*)0))
1058 {
1059 if ((s = (t42_encode_state_t *) span_alloc(sizeof(*s))) == NULL((void*)0))
1060 return NULL((void*)0);
1061 /*endif*/
1062 }
1063 /*endif*/
1064 memset(s, 0, sizeof(*s));
1065 span_log_init(&s->logging, SPAN_LOG_NONE, NULL((void*)0));
1066 span_log_set_protocol(&s->logging, "T.42");
1067
1068 s->quality = 90;
1069 s->image_type = T4_IMAGE_TYPE_COLOUR_8BIT;
1070
1071 s->row_read_handler = handler;
1072 s->row_read_user_data = user_data;
1073
1074 t42_encode_restart(s, image_width, image_length);
1075
1076 return s;
1077}
1078/*- End of function --------------------------------------------------------*/
1079
1080SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_release(t42_encode_state_t *s)
1081{
1082 return 0;
1083}
1084/*- End of function --------------------------------------------------------*/
1085
1086SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_encode_free(t42_encode_state_t *s)
1087{
1088 int ret;
1089
1090 ret = t42_encode_release(s);
1091 span_free(s);
1092 return ret;
1093}
1094/*- End of function --------------------------------------------------------*/
1095
1096/* Error handler for IJG library */
1097static void jpg_decode_error_exit(j_common_ptr cinfo)
1098{
1099 t42_decode_state_t *s;
1100
1101 s = (t42_decode_state_t *) cinfo->client_data;
1102 (*cinfo->err->format_message)(cinfo, s->error_message);
1103 longjmp(s->escape, 1);
1104}
1105/*- End of function --------------------------------------------------------*/
1106
1107/* This is the error catcher */
1108static struct jpeg_error_mgr decode_error_handler =
1109{
1110#if defined(_MSC_VER) || defined(__sunos) || defined(__solaris) || defined(__sun)
1111 jpg_decode_error_exit,
1112 0,
1113 jpg_decode_error_exit
1114#else
1115 .error_exit = jpg_decode_error_exit,
1116 .output_message = jpg_decode_error_exit
1117#endif
1118};
1119
1120static int t42_itulab_jpeg_to_srgb(t42_decode_state_t *s)
1121{
1122 int i;
1123
1124 if (s->compressed_buf == NULL((void*)0))
1125 return -1;
1126 /*endif*/
1127
1128#if defined(HAVE_OPEN_MEMSTREAM1)
1129 if ((s->in = fmemopen(s->compressed_buf, s->compressed_image_size, "r")) == NULL((void*)0))
1130 {
1131 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to fmemopen().\n");
1132 return -1;
1133 }
1134 /*endif*/
1135#else
1136 if ((s->in = tmpfile()) == NULL((void*)0))
1137 {
1138 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
1139 return -1;
1140 }
1141 /*endif*/
1142 if (fwrite(s->compressed_buf, 1, s->compressed_image_size, s->in) != s->compressed_image_size)
1143 {
1144 fclose(s->in);
1145 s->in = NULL((void*)0);
1146 return -1;
1147 }
1148 /*endif*/
1149 if (fseek(s->in, 0, SEEK_SET0) != 0)
1150 {
1151 fclose(s->in);
1152 s->in = NULL((void*)0);
1153 return -1;
1154 }
1155 /*endif*/
1156#endif
1157 s->scan_line_out = NULL((void*)0);
1158
1159 if (setjmp(s->escape)_setjmp (s->escape))
1160 {
1161 if (s->error_message[0])
1162 span_log(&s->logging, SPAN_LOG_FLOW, "%s\n", s->error_message);
1163 else
1164 span_log(&s->logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n");
1165 /*endif*/
1166 if (s->scan_line_out)
1167 {
1168 span_free(s->scan_line_out);
1169 s->scan_line_out = NULL((void*)0);
1170 }
1171 /*endif*/
1172 if (s->in)
1173 {
1174 fclose(s->in);
1175 s->in = NULL((void*)0);
1176 }
1177 /*endif*/
1178 return -1;
1179 }
1180 /* Create input decompressor. */
1181 s->decompressor.err = jpeg_std_error(&decode_error_handler);
1182 s->decompressor.client_data = (void *) s;
1183
1184 jpeg_create_decompress(&s->decompressor)jpeg_CreateDecompress((&s->decompressor), 62, (size_t)
sizeof(struct jpeg_decompress_struct))
;
1185 jpeg_stdio_src(&s->decompressor, s->in);
1186
1187 /* Get the FAX tags */
1188 for (i = 0; i < 16; i++)
1189 jpeg_save_markers(&s->decompressor, JPEG_APP00xE0 + i, 0xFFFF);
1190 /*endfor*/
1191
1192 /* Take the header */
1193 jpeg_read_header(&s->decompressor, false0);
1194 /* Sanity check and parameter check */
1195 if (!is_itu_fax(s, s->decompressor.marker_list))
1196 {
1197 span_log(&s->logging, SPAN_LOG_FLOW, "Is not an ITU FAX.\n");
1198 return -1;
1199 }
1200 /*endif*/
1201 /* Copy size, resolution, etc */
1202 s->image_width = s->decompressor.image_width;
1203 s->image_length = s->decompressor.image_height;
1204 s->samples_per_pixel = s->decompressor.num_components;
1205
1206 if (s->samples_per_pixel == 3)
1207 {
1208 /* Now we can force the input colour space. For ITULab, we use YCbCr as a "don't touch" marker */
1209 s->decompressor.out_color_space = JCS_YCbCr;
1210 span_log(&s->logging,
1211 SPAN_LOG_FLOW,
1212 "Sampling %d %d %d %d %d %d\n",
1213 s->decompressor.comp_info[0].h_samp_factor,
1214 s->decompressor.comp_info[0].v_samp_factor,
1215 s->decompressor.comp_info[1].h_samp_factor,
1216 s->decompressor.comp_info[1].v_samp_factor,
1217 s->decompressor.comp_info[2].h_samp_factor,
1218 s->decompressor.comp_info[2].v_samp_factor);
1219 }
1220 else
1221 {
1222 s->decompressor.out_color_space = JCS_GRAYSCALE;
1223 span_log(&s->logging,
1224 SPAN_LOG_FLOW,
1225 "Sampling %d %d\n",
1226 s->decompressor.comp_info[0].h_samp_factor,
1227 s->decompressor.comp_info[0].v_samp_factor);
1228 }
1229 /*endif*/
1230
1231 jpeg_start_decompress(&s->decompressor);
1232
1233 if ((s->scan_line_in = span_alloc(s->samples_per_pixel*s->image_width)) == NULL((void*)0))
1234 return -1;
1235 /*endif*/
1236
1237 if (s->samples_per_pixel == 3)
1238 {
1239 if ((s->scan_line_out = span_alloc(s->samples_per_pixel*s->image_width)) == NULL((void*)0))
1240 return -1;
1241 /*endif*/
1242
1243 while (s->decompressor.output_scanline < s->image_length)
1244 {
1245 jpeg_read_scanlines(&s->decompressor, &s->scan_line_in, 1);
1246 lab_to_srgb(&s->lab, s->scan_line_out, s->scan_line_in, s->image_width);
1247 s->row_write_handler(s->row_write_user_data, s->scan_line_out, s->samples_per_pixel*s->image_width);
1248 }
1249 /*endwhile*/
1250 }
1251 else
1252 {
1253 while (s->decompressor.output_scanline < s->image_length)
1254 {
1255 jpeg_read_scanlines(&s->decompressor, &s->scan_line_in, 1);
1256 s->row_write_handler(s->row_write_user_data, s->scan_line_in, s->image_width);
1257 }
1258 /*endwhile*/
1259 }
1260 /*endif*/
1261
1262 if (s->scan_line_in)
1263 {
1264 span_free(s->scan_line_in);
1265 s->scan_line_in = NULL((void*)0);
1266 }
1267 /*endif*/
1268 if (s->scan_line_out)
1269 {
1270 span_free(s->scan_line_out);
1271 s->scan_line_out = NULL((void*)0);
1272 }
1273 /*endif*/
1274 jpeg_finish_decompress(&s->decompressor);
1275 jpeg_destroy_decompress(&s->decompressor);
1276 fclose(s->in);
1277 s->in = NULL((void*)0);
1278
1279 return 0;
1280}
1281/*- End of function --------------------------------------------------------*/
1282
1283SPAN_DECLARE(void)__attribute__((visibility("default"))) void t42_decode_rx_status(t42_decode_state_t *s, int status)
1284{
1285 span_log(&s->logging, SPAN_LOG_FLOW, "Signal status is %s (%d)\n", signal_status_to_str(status), status);
1286 switch (status)
1287 {
1288 case SIG_STATUS_TRAINING_IN_PROGRESS:
1289 case SIG_STATUS_TRAINING_FAILED:
1290 case SIG_STATUS_TRAINING_SUCCEEDED:
1291 case SIG_STATUS_CARRIER_UP:
1292 /* Ignore these */
1293 break;
1294 case SIG_STATUS_CARRIER_DOWN:
1295 case SIG_STATUS_END_OF_DATA:
1296 /* Finalise the image */
1297 if (!s->end_of_data)
1298 {
1299 if (t42_itulab_jpeg_to_srgb(s))
1300 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to convert from ITULAB.\n");
1301 /*endif*/
1302 s->end_of_data = true1;
1303 }
1304 /*endif*/
1305 break;
1306 default:
1307 span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected rx status - %d!\n", status);
1308 break;
1309 }
1310 /*endswitch*/
1311}
1312/*- End of function --------------------------------------------------------*/
1313
1314SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_put(t42_decode_state_t *s, const uint8_t data[], size_t len)
1315{
1316 uint8_t *buf;
1317
1318 if (len == 0)
1319 {
1320 if (!s->end_of_data)
1321 {
1322 if (t42_itulab_jpeg_to_srgb(s))
1323 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to convert from ITULAB.\n");
1324 /*endif*/
1325 s->end_of_data = true1;
1326 }
1327 /*endif*/
1328 return T4_DECODE_OK;
1329 }
1330 /*endif*/
1331
1332 if (s->compressed_image_size + len > s->buf_size)
1333 {
1334 if ((buf = (uint8_t *) span_realloc(s->compressed_buf, s->compressed_image_size + len + 10000)) == NULL((void*)0))
1335 return -1;
1336 /*endif*/
1337 s->buf_size = s->compressed_image_size + len + 10000;
1338 s->compressed_buf = buf;
1339 }
1340 /*endif*/
1341 memcpy(&s->compressed_buf[s->compressed_image_size], data, len);
1342 s->compressed_image_size += len;
1343 return 0;
1344}
1345/*- End of function --------------------------------------------------------*/
1346
1347SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_set_row_write_handler(t42_decode_state_t *s,
1348 t4_row_write_handler_t handler,
1349 void *user_data)
1350{
1351 s->row_write_handler = handler;
1352 s->row_write_user_data = user_data;
1353 return 0;
1354}
1355/*- End of function --------------------------------------------------------*/
1356
1357SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_set_comment_handler(t42_decode_state_t *s,
1358 uint32_t max_comment_len,
1359 t4_row_write_handler_t handler,
1360 void *user_data)
1361{
1362 s->max_comment_len = max_comment_len;
1363 s->comment_handler = handler;
1364 s->comment_user_data = user_data;
1365 return 0;
1366}
1367/*- End of function --------------------------------------------------------*/
1368
1369SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_set_image_size_constraints(t42_decode_state_t *s,
1370 uint32_t max_xd,
1371 uint32_t max_yd)
1372{
1373 return 0;
1374}
1375/*- End of function --------------------------------------------------------*/
1376
1377SPAN_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t t42_decode_get_image_width(t42_decode_state_t *s)
1378{
1379 return s->image_width;
1380}
1381/*- End of function --------------------------------------------------------*/
1382
1383SPAN_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t t42_decode_get_image_length(t42_decode_state_t *s)
1384{
1385 return s->image_length;
1386}
1387/*- End of function --------------------------------------------------------*/
1388
1389SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_get_compressed_image_size(t42_decode_state_t *s)
1390{
1391 return s->compressed_image_size;
1392}
1393/*- End of function --------------------------------------------------------*/
1394
1395SPAN_DECLARE(logging_state_t *)__attribute__((visibility("default"))) logging_state_t * t42_decode_get_logging_state(t42_decode_state_t *s)
1396{
1397 return &s->logging;
1398}
1399/*- End of function --------------------------------------------------------*/
1400
1401SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_restart(t42_decode_state_t *s)
1402{
1403 if (s->itu_ycc)
1404 {
1405 /* ITU-YCC */
1406 /* Illuminant D65 */
1407 //set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
1408 set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
1409 set_lab_gamut(&s->lab, 0, 100, -127, 127, -127, 127, false0);
1410 }
1411 else
1412 {
1413 /* ITULAB */
1414 /* Illuminant D50 */
1415 //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
1416 set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
1417 set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false0);
1418 }
1419 /*endif*/
1420
1421 s->end_of_data = false0;
1422 s->compressed_image_size = 0;
1423
1424 s->error_message[0] = '\0';
1425
1426 return 0;
1427}
1428/*- End of function --------------------------------------------------------*/
1429
1430SPAN_DECLARE(t42_decode_state_t *)__attribute__((visibility("default"))) t42_decode_state_t * t42_decode_init(t42_decode_state_t *s,
1431 t4_row_write_handler_t handler,
1432 void *user_data)
1433{
1434 if (s == NULL((void*)0))
1435 {
1436 if ((s = (t42_decode_state_t *) span_alloc(sizeof(*s))) == NULL((void*)0))
1437 return NULL((void*)0);
1438 /*endif*/
1439 }
1440 /*endif*/
1441 memset(s, 0, sizeof(*s));
1442 span_log_init(&s->logging, SPAN_LOG_NONE, NULL((void*)0));
1443 span_log_set_protocol(&s->logging, "T.42");
1444
1445 s->row_write_handler = handler;
1446 s->row_write_user_data = user_data;
1447
1448 s->buf_size = 0;
1449 s->compressed_buf = NULL((void*)0);
1450
1451 t42_decode_restart(s);
1452
1453 return s;
1454}
1455/*- End of function --------------------------------------------------------*/
1456
1457SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_release(t42_decode_state_t *s)
1458{
1459 if (s->scan_line_in)
1460 {
1461 span_free(s->scan_line_in);
1462 s->scan_line_in = NULL((void*)0);
1463 }
1464 /*endif*/
1465 if (s->scan_line_out)
1466 {
1467 span_free(s->scan_line_out);
1468 s->scan_line_out = NULL((void*)0);
1469 }
1470 /*endif*/
1471 jpeg_destroy_decompress(&s->decompressor);
1472 if (s->in)
1473 {
1474 fclose(s->in);
1475 s->in = NULL((void*)0);
1476 }
1477 /*endif*/
1478 if (s->comment)
1479 {
1480 span_free(s->comment);
1481 s->comment = NULL((void*)0);
1482 }
1483 /*endif*/
1484 return 0;
1485}
1486/*- End of function --------------------------------------------------------*/
1487
1488SPAN_DECLARE(int)__attribute__((visibility("default"))) int t42_decode_free(t42_decode_state_t *s)
1489{
1490 int ret;
1491
1492 ret = t42_decode_release(s);
1493 span_free(s);
1494 return ret;
1495}
1496/*- End of function --------------------------------------------------------*/
1497/*- End of file ------------------------------------------------------------*/