Bug Summary

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