FAX T.6 decompression fixed for images with black in the last pixel of lines.

Colour and grey images can down be dithered down to bi-level images for transmission as faxes.
More movement towards T.42 support
This commit is contained in:
Steve Underwood 2012-08-04 03:45:09 +08:00
parent e35221b981
commit e523076274
29 changed files with 916 additions and 446 deletions

View File

@ -20,6 +20,7 @@ AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS) AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \ DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \
$(srcdir)/cielab_luts.h \
$(srcdir)/math_fixed_tables.h \ $(srcdir)/math_fixed_tables.h \
$(srcdir)/v17_v32bis_rx_fixed_rrc.h \ $(srcdir)/v17_v32bis_rx_fixed_rrc.h \
$(srcdir)/v17_v32bis_rx_floating_rrc.h \ $(srcdir)/v17_v32bis_rx_floating_rrc.h \
@ -58,6 +59,7 @@ EXTRA_DIST = floating_fudge.h \
libtiff.2008.vcproj \ libtiff.2008.vcproj \
filter_tools.c \ filter_tools.c \
make_at_dictionary.c \ make_at_dictionary.c \
make_cielab_luts.c \
make_math_fixed_tables.c \ make_math_fixed_tables.c \
make_modem_filter.c \ make_modem_filter.c \
msvc/config.h \ msvc/config.h \
@ -344,6 +346,7 @@ noinst_HEADERS = cielab_luts.h \
mmx_sse_decs.h \ mmx_sse_decs.h \
t30_local.h \ t30_local.h \
t4_t6_decode_states.h \ t4_t6_decode_states.h \
t42_t43_local.h \
v17_v32bis_rx_constellation_maps.h \ v17_v32bis_rx_constellation_maps.h \
v17_v32bis_tx_constellation_maps.h \ v17_v32bis_tx_constellation_maps.h \
v29tx_constellation_maps.h v29tx_constellation_maps.h
@ -351,6 +354,9 @@ noinst_HEADERS = cielab_luts.h \
make_at_dictionary$(EXEEXT): $(top_srcdir)/src/make_at_dictionary.c make_at_dictionary$(EXEEXT): $(top_srcdir)/src/make_at_dictionary.c
$(CC_FOR_BUILD) -o make_at_dictionary$(EXEEXT) $(top_srcdir)/src/make_at_dictionary.c -DHAVE_CONFIG_H -I$(top_builddir)/src $(CC_FOR_BUILD) -o make_at_dictionary$(EXEEXT) $(top_srcdir)/src/make_at_dictionary.c -DHAVE_CONFIG_H -I$(top_builddir)/src
make_cielab_luts$(EXEEXT): $(top_srcdir)/src/make_cielab_luts.c
$(CC_FOR_BUILD) -o make_cielab_luts$(EXEEXT) $(top_srcdir)/src/make_cielab_luts.c -DHAVE_CONFIG_H -I$(top_builddir)/src -lm
make_math_fixed_tables$(EXEEXT): $(top_srcdir)/src/make_math_fixed_tables.c make_math_fixed_tables$(EXEEXT): $(top_srcdir)/src/make_math_fixed_tables.c
$(CC_FOR_BUILD) -o make_math_fixed_tables$(EXEEXT) $(top_srcdir)/src/make_math_fixed_tables.c -DHAVE_CONFIG_H -I$(top_builddir)/src -lm $(CC_FOR_BUILD) -o make_math_fixed_tables$(EXEEXT) $(top_srcdir)/src/make_math_fixed_tables.c -DHAVE_CONFIG_H -I$(top_builddir)/src -lm
@ -378,6 +384,13 @@ t4_rx.$(OBJEXT): spandsp/version.h
t4_rx.lo: spandsp/version.h t4_rx.lo: spandsp/version.h
t42.$(OBJEXT): cielab_luts.h
t42.lo: cielab_luts.h
cielab_luts.h: make_cielab_luts$(EXEEXT)
./make_cielab_luts$(EXEEXT) >cielab_luts.h
V17_V32BIS_RX_INCL = v17_v32bis_rx_fixed_rrc.h \ V17_V32BIS_RX_INCL = v17_v32bis_rx_fixed_rrc.h \
v17_v32bis_rx_floating_rrc.h v17_v32bis_rx_floating_rrc.h

View File

@ -1,32 +1,4 @@
/* static const float srgb_to_linear[256] =
* SpanDSP - a series of DSP components for telephony
*
* cielab_luts.h
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2011 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if defined(T42_USE_LUTS)
static const float sRGB_to_linear[256] =
{ {
0.000000, 0.000000,
0.000302, 0.000302,
@ -168,7 +140,7 @@ static const float sRGB_to_linear[256] =
0.248036, 0.248036,
0.251995, 0.251995,
0.255990, 0.255990,
0.260021, 0.260022,
0.264090, 0.264090,
0.268196, 0.268196,
0.272338, 0.272338,
@ -267,7 +239,7 @@ static const float sRGB_to_linear[256] =
0.831396, 0.831396,
0.839397, 0.839397,
0.847443, 0.847443,
0.855533, 0.855534,
0.863669, 0.863669,
0.871850, 0.871850,
0.880075, 0.880075,
@ -285,8 +257,7 @@ static const float sRGB_to_linear[256] =
0.982319, 0.982319,
0.991137 0.991137
}; };
static const uint8_t linear_to_srgb[4096] =
static const uint8_t linear_to_sRGB[4096] =
{ {
0, 0,
0, 0,
@ -4385,5 +4356,3 @@ static const uint8_t linear_to_sRGB[4096] =
255, 255,
255 255
}; };
#endif
/*- End of file ------------------------------------------------------------*/

View File

@ -74,6 +74,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -118,6 +119,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
#include "spandsp/private/t30.h" #include "spandsp/private/t30.h"

View File

@ -80,9 +80,9 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
#include "spandsp/private/image_translate.h"
static int image_colour16_to_gray8_row(uint8_t mono[], uint16_t colour[], int pixels) static int image_colour16_to_gray8_row(uint8_t mono[], uint16_t colour[], int pixels)
{ {
@ -154,12 +154,14 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[], size_t le
int input_width; int input_width;
int input_length; int input_length;
int x; int x;
double c1;
double c2;
#if defined(SPANDSP_USE_FIXED_POINT) #if defined(SPANDSP_USE_FIXED_POINT)
int c1;
int c2;
int frac_row; int frac_row;
int frac_col; int frac_col;
#else #else
double c1;
double c2;
double int_part; double int_part;
double frac_row; double frac_row;
double frac_col; double frac_col;
@ -200,15 +202,15 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[], size_t le
} }
#if defined(SPANDSP_USE_FIXED_POINT) #if defined(SPANDSP_USE_FIXED_POINT)
frac_row = s->raw_output_row*input_length/output_length; frac_row = ((s->raw_output_row*256*input_length)/output_length) & 0xFF;
frac_row = s->raw_output_row*input_length - frac_row*output_length;
for (i = 0; i < output_width; i++) for (i = 0; i < output_width; i++)
{ {
x = i*input_width/output_width; x = i*256*input_width/output_width;
frac_col = x - x*output_width; frac_col = x & 0xFF;
c1 = s->raw_pixel_row[0][x] + (s->raw_pixel_row[0][x + 1] - s->raw_pixel_row[0][x])*frac_col; x >>= 8;
c2 = s->raw_pixel_row[1][x] + (s->raw_pixel_row[1][x + 1] - s->raw_pixel_row[1][x])*frac_col; c1 = s->raw_pixel_row[0][x] + (((s->raw_pixel_row[0][x + 1] - s->raw_pixel_row[0][x])*frac_col) >> 8);
buf[i] = saturateu8(c1 + (c2 - c1)*frac_row); c2 = s->raw_pixel_row[1][x] + (((s->raw_pixel_row[1][x + 1] - s->raw_pixel_row[1][x])*frac_col) >> 8);
buf[i] = saturateu8(c1 + (((c2 - c1)*frac_row) >> 8));
} }
#else #else
frac_row = modf((double) s->raw_output_row*input_length/output_length, &int_part); frac_row = modf((double) s->raw_output_row*input_length/output_length, &int_part);
@ -368,6 +370,7 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta
int input_width, int input_width,
int input_length, int input_length,
int output_width, int output_width,
int output_length,
t4_row_read_handler_t row_read_handler, t4_row_read_handler_t row_read_handler,
void *row_read_user_data) void *row_read_user_data)
{ {
@ -385,9 +388,19 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta
s->input_width = input_width; s->input_width = input_width;
s->input_length = input_length; s->input_length = input_length;
s->resize = (output_width > 0); if ((s->resize = (output_width > 0)))
s->output_width = (s->resize) ? output_width : s->input_width; {
s->output_length = (s->resize) ? s->input_length*s->output_width/s->input_width : s->input_length; s->output_width = output_width;
if (output_length > 0)
s->output_length = output_length;
else
s->output_length = (s->input_length*s->output_width)/s->input_width;
}
else
{
s->output_width = s->input_width;
s->output_length = s->input_length;
}
switch (s->input_format) switch (s->input_format)
{ {

View File

@ -0,0 +1,92 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* make_cielab_luts.c - Create the look up tables for CIELab colour management
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2011 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <memory.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#endif
typedef struct
{
float L;
float a;
float b;
} cielab_t;
int main(int argc, char *argv[])
{
float r;
uint8_t srgb;
int i;
printf("static const float srgb_to_linear[256] =\n");
printf("{\n");
for (i = 0; i < 256; i++)
{
/* Start with "i" as the sRGB value */
r = i/256.0f;
/* sRGB to Linear RGB */
r = (r > 0.04045f) ? powf((r + 0.055f)/1.055f, 2.4f) : r/12.92f;
printf((i < 255) ? " %f,\n" : " %f\n", r);
}
printf("};\n");
printf("static const uint8_t linear_to_srgb[4096] =\n");
printf("{\n");
for (i = 0; i < 4096; i++)
{
/* Start with "i" as the linear RGB value */
/* Linear RGB to sRGB */
r = i/4096.0f;
r = (r > 0.0031308f) ? (1.055f*powf(r, 1.0f/2.4f) - 0.055f) : r*12.92f;
r = floorf(r*256.0f);
srgb = (r < 0) ? 0 : (r <= 255) ? r : 255;
printf((i < 4095) ? " %d,\n" : " %d\n", srgb);
}
printf("};\n");
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -75,9 +75,11 @@ SPAN_DECLARE(int) image_translate_get_output_length(image_translate_state_t *s);
\param input_format x \param input_format x
\param input_width The width of the source image, in pixels. \param input_width The width of the source image, in pixels.
\param input_length The length of the source image, in pixels. \param input_length The length of the source image, in pixels.
\param output_width The width of the output image, in pixels. The length of the output image \param output_width The width of the output image, in pixels. If this is set <= 0 the image
will be derived automatically from this and the source image dimension, to main the will not be resized.
geometry of the original image. \param output_length The length of the output image, in pixels. If this is set to <= 0 the
output length will be derived automatically from the width, to maintain the geometry
of the original image.
\param row_read_handler A callback routine used to pull rows of pixels from the source image \param row_read_handler A callback routine used to pull rows of pixels from the source image
into the translation process. into the translation process.
\param row_read_user_data An opaque point passed to read_row_handler \param row_read_user_data An opaque point passed to read_row_handler
@ -87,6 +89,7 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta
int input_width, int input_width,
int input_length, int input_length,
int output_width, int output_width,
int output_length,
t4_row_read_handler_t row_read_handler, t4_row_read_handler_t row_read_handler,
void *row_read_user_data); void *row_read_user_data);

View File

@ -53,6 +53,9 @@ struct t42_encode_state_s
lab_params_t lab_params; lab_params_t lab_params;
/*! \brief The size of the compressed image, in bytes. */
int compressed_image_size;
/*! \brief Error and flow logging control */ /*! \brief Error and flow logging control */
logging_state_t logging; logging_state_t logging;
}; };
@ -68,6 +71,8 @@ struct t42_decode_state_s
t4_row_write_handler_t comment_handler; t4_row_write_handler_t comment_handler;
/*! An opaque pointer passed to comment_handler() */ /*! An opaque pointer passed to comment_handler() */
void *comment_user_data; void *comment_user_data;
/*! The maximum length of comment to be passed to the comment handler */
uint32_t max_comment_len;
lab_params_t lab_params; lab_params_t lab_params;
@ -78,6 +83,12 @@ struct t42_decode_state_s
/*! Length of data pointed to by comment */ /*! Length of data pointed to by comment */
size_t comment_len; size_t comment_len;
/*! \brief The size of the compressed image, in bytes. */
int compressed_image_size;
int buf_size;
uint8_t *compressed_buf;
/*! \brief Error and flow logging control */ /*! \brief Error and flow logging control */
logging_state_t logging; logging_state_t logging;
}; };

View File

@ -54,6 +54,12 @@ typedef struct
int image_buffer_size; int image_buffer_size;
/*! \brief Row counter for playing out the rows of the image. */ /*! \brief Row counter for playing out the rows of the image. */
int row; int row;
/*! \brief Image length of the image in the file. This is used when the
image is resized or dithered flat. */
int image_length;
/*! \brief Row counter used when the image is resized or dithered flat. */
int raw_row;
} t4_tx_tiff_state_t; } t4_tx_tiff_state_t;
/*! /*!
@ -132,6 +138,8 @@ struct t4_tx_state_s
t85_encode_state_t t85; t85_encode_state_t t85;
} encoder; } encoder;
image_translate_state_t translator;
/* Supporting information, like resolutions, which the backend may want. */ /* Supporting information, like resolutions, which the backend may want. */
t4_tx_metadata_t metadata; t4_tx_metadata_t metadata;

View File

@ -123,11 +123,11 @@ struct t85_decode_state_s
t4_row_write_handler_t comment_handler; t4_row_write_handler_t comment_handler;
/*! An opaque pointer passed to comment_handler() */ /*! An opaque pointer passed to comment_handler() */
void *comment_user_data; void *comment_user_data;
/*! The maximum length of comment to be passed to the comment handler */
uint32_t max_comment_len;
uint8_t min_bit_planes; uint8_t min_bit_planes;
uint8_t max_bit_planes; uint8_t max_bit_planes;
/*! The maximum length of comment to be passed to the comment handler */
uint32_t max_comment_len;
/*! The maximum permitted width of the full image, in pixels */ /*! The maximum permitted width of the full image, in pixels */
uint32_t max_xd; uint32_t max_xd;
/*! The maximum permitted height of the full image, in pixels */ /*! The maximum permitted height of the full image, in pixels */

View File

@ -58,19 +58,15 @@ SPAN_DECLARE(void) set_lab_gamut(lab_params_t *s, int L_min, int L_max, int a_mi
SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, int a_Q, int b_P, int b_Q); SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, int a_Q, int b_P, int b_Q);
SPAN_DECLARE(void) set_illuminant_from_code(lab_params_t *s, const uint8_t code[4]); SPAN_DECLARE(int) t42_itulab_to_itulab(logging_state_t *logging, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height);
SPAN_DECLARE(void) set_gamut_from_code(lab_params_t *s, const uint8_t code[12]); SPAN_DECLARE(int) t42_itulab_to_jpeg(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen);
SPAN_DECLARE(int) t42_itulab_to_itulab(tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height, char *emsg, size_t max_emsg_bytes); SPAN_DECLARE(int) t42_jpeg_to_itulab(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen);
SPAN_DECLARE(int) t42_itulab_to_jpeg(lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, char *emsg, size_t max_emsg_bytes); SPAN_DECLARE(int) t42_srgb_to_itulab(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height);
SPAN_DECLARE(int) t42_jpeg_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, char *emsg, size_t max_emsg_bytes); SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, tdata_t dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t *width, uint32_t *height);
SPAN_DECLARE(int) t42_srgb_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height, char *emsg, size_t max_emsg_bytes);
SPAN_DECLARE(int) t42_itulab_to_srgb(lab_params_t *s, tdata_t dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t *width, uint32_t *height, char *emsg, size_t max_emsg_bytes);
SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s,
uint32_t l0, uint32_t l0,

View File

@ -199,6 +199,23 @@ typedef enum
T4_LENGTH_1200_US_LEGAL = 0 T4_LENGTH_1200_US_LEGAL = 0
} t4_image_length_t; } t4_image_length_t;
/*! Return values from the T.85 decoder */
typedef enum
{
/*! More image data is needed */
T4_DECODE_MORE_DATA = 0,
/*! Image completed successfully */
T4_DECODE_OK = -1,
/*! The decoder has interrupted */
T4_DECODE_INTERRUPT = -2,
/*! An abort was found in the image data */
T4_DECODE_ABORTED = -3,
/*! A memory allocation error occurred */
T4_DECODE_NOMEM = -4,
/*! The image data is invalid. */
T4_DECODE_INVALID_DATA = -5
} t4_decoder_status_t;
/*! /*!
T.4 FAX compression/decompression descriptor. This defines the working state T.4 FAX compression/decompression descriptor. This defines the working state
for a single instance of a T.4 FAX compression or decompression channel. for a single instance of a T.4 FAX compression or decompression channel.

View File

@ -53,24 +53,6 @@ enum
T85_LRLTWO = 0x40 T85_LRLTWO = 0x40
}; };
/*! Return values from the T.85 decoder */
enum
{
/*! More image data is needed */
T85_MORE_DATA = 0,
/*! Image completed successfully */
T85_OK = -1,
/*! The decoder has interrupted */
T85_INTERRUPT = -2,
/*! An abort was found in the image data */
T85_ABORTED = -3,
/*! A memory allocation error occurred */
T85_NOMEM = -4,
/*! The image data is invalid. This includes finding values
in the BIH which lie outside the T.85 domain */
T85_INVALID_DATA = -5
};
/*! State of a working instance of the T.85 encoder */ /*! State of a working instance of the T.85 encoder */
typedef struct t85_encode_state_s t85_encode_state_t; typedef struct t85_encode_state_s t85_encode_state_t;

View File

@ -61,6 +61,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -89,6 +90,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
#include "spandsp/private/t30.h" #include "spandsp/private/t30.h"
@ -1179,9 +1181,11 @@ int t30_build_dis_or_dtc(t30_state_t *s)
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_T85_COMPRESSION)) if ((s->supported_compressions & T30_SUPPORT_T85_COMPRESSION))
{ {
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE); /* Bit 79 set with bit 78 clear is invalid, so only check for L0
support here. */
if ((s->supported_compressions & T30_SUPPORT_T85_L0_COMPRESSION)) if ((s->supported_compressions & T30_SUPPORT_T85_L0_COMPRESSION))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE);
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE);
} }
//if ((s->supported_compressions & T30_SUPPORT_T89_COMPRESSION)) //if ((s->supported_compressions & T30_SUPPORT_T89_COMPRESSION))
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T89_CAPABLE); // set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T89_CAPABLE);
@ -1970,8 +1974,6 @@ static int start_sending_document(t30_state_t *s)
if (s->use_own_tz) if (s->use_own_tz)
t4_tx_set_header_tz(&s->t4.tx, &s->tz); t4_tx_set_header_tz(&s->t4.tx, &s->tz);
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
/* The minimum scan time to be used can't be evaluated until we know the Y resolution, and /* The minimum scan time to be used can't be evaluated until we know the Y resolution, and
must be evaluated before the minimum scan row bits can be evaluated. */ must be evaluated before the minimum scan row bits can be evaluated. */
if ((min_row_bits = set_min_scan_time_code(s)) < 0) if ((min_row_bits = set_min_scan_time_code(s)) < 0)
@ -1984,6 +1986,8 @@ static int start_sending_document(t30_state_t *s)
if (tx_start_page(s)) if (tx_start_page(s))
return -1; return -1;
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
s->image_width = t4_tx_get_image_width(&s->t4.tx); s->image_width = t4_tx_get_image_width(&s->t4.tx);
if (s->error_correcting_mode) if (s->error_correcting_mode)
{ {
@ -2069,26 +2073,44 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
/* 256 octets per ECM frame */ /* 256 octets per ECM frame */
s->octets_per_ecm_frame = 256; s->octets_per_ecm_frame = 256;
/* Select the compression to use. */ /* Select the compression to use. */
if (s->error_correcting_mode if (!s->error_correcting_mode)
&&
(s->supported_compressions & T30_SUPPORT_T85_COMPRESSION)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE))
{ {
if (s->supported_compressions & T30_SUPPORT_T85_L0_COMPRESSION /* Without error correction our choices are very limited */
if ((s->supported_compressions & T30_SUPPORT_T4_2D_COMPRESSION)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_ITU_T4_2D;
}
else
{
s->line_encoding = T4_COMPRESSION_ITU_T4_1D;
}
}
else
{
#if defined(SPANDSP_SUPPORT_T42x) || defined(SPANDSP_SUPPORT_T43)
/* With error correction colour may be possible/required */
if (0)
{
s->line_encoding = T4_COMPRESSION_ITU_T85_L0;
}
else
#endif
{
if ((s->supported_compressions & T30_SUPPORT_T85_L0_COMPRESSION)
&& &&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE)) test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE))
{ {
s->line_encoding = T4_COMPRESSION_ITU_T85_L0; s->line_encoding = T4_COMPRESSION_ITU_T85_L0;
} }
else else if ((s->supported_compressions & T30_SUPPORT_T85_COMPRESSION)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE))
{ {
s->line_encoding = T4_COMPRESSION_ITU_T85; s->line_encoding = T4_COMPRESSION_ITU_T85;
} }
} else if ((s->supported_compressions & T30_SUPPORT_T6_COMPRESSION)
else if (s->error_correcting_mode
&&
(s->supported_compressions & T30_SUPPORT_T6_COMPRESSION)
&& &&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE)) test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
{ {
@ -2104,6 +2126,8 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->line_encoding = T4_COMPRESSION_ITU_T4_1D; s->line_encoding = T4_COMPRESSION_ITU_T4_1D;
} }
}
}
span_log(&s->logging, SPAN_LOG_FLOW, "Selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding); span_log(&s->logging, SPAN_LOG_FLOW, "Selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3)) switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
{ {
@ -2357,7 +2381,21 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
s->image_width = widths[i][dcs_frame[5] & (DISBIT2 | DISBIT1)]; s->image_width = widths[i][dcs_frame[5] & (DISBIT2 | DISBIT1)];
/* Check which compression we will use. */ /* Check which compression the far end has decided to use. */
#if defined(SPANDSP_SUPPORT_T42x)
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE))
{
s->line_encoding = T4_COMPRESSION_ITU_T42;
}
else
#endif
#if defined(SPANDSP_SUPPORT_T43)
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T43_MODE))
{
s->line_encoding = T4_COMPRESSION_ITU_T43;
}
else
#endif
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_L0_MODE)) if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_L0_MODE))
{ {
s->line_encoding = T4_COMPRESSION_ITU_T85_L0; s->line_encoding = T4_COMPRESSION_ITU_T85_L0;

View File

@ -61,6 +61,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -89,6 +90,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
#include "spandsp/private/t30.h" #include "spandsp/private/t30.h"
@ -700,7 +702,7 @@ SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_c
| T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION
| T30_SUPPORT_T6_COMPRESSION | T30_SUPPORT_T6_COMPRESSION
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
| T30_SUPPORT_T42_COMPRESSION //| T30_SUPPORT_T42_COMPRESSION
#endif #endif
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
| T30_SUPPORT_T43_COMPRESSION | T30_SUPPORT_T43_COMPRESSION

View File

@ -61,6 +61,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -88,6 +89,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
#include "spandsp/private/t30.h" #include "spandsp/private/t30.h"

View File

@ -74,6 +74,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -116,6 +117,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
#include "spandsp/private/t30.h" #include "spandsp/private/t30.h"

View File

@ -64,6 +64,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -94,6 +95,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
#include "spandsp/private/t30.h" #include "spandsp/private/t30.h"

View File

@ -61,7 +61,10 @@
#define T42_USE_LUTS #define T42_USE_LUTS
#include "t42_t43_local.h"
#if defined(T42_USE_LUTS)
#include "cielab_luts.h" #include "cielab_luts.h"
#endif
typedef struct typedef struct
{ {
@ -197,7 +200,7 @@ SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, in
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) set_illuminant_from_code(lab_params_t *s, const uint8_t code[4]) void set_illuminant_from_code(logging_state_t *logging, lab_params_t *s, const uint8_t code[4])
{ {
int i; int i;
int colour_temp; int colour_temp;
@ -205,31 +208,33 @@ SPAN_DECLARE(void) set_illuminant_from_code(lab_params_t *s, const uint8_t code[
if (code[0] == 'C' && code[1] == 'T') if (code[0] == 'C' && code[1] == 'T')
{ {
colour_temp = pack_16(&code[2]); colour_temp = pack_16(&code[2]);
printf("Illuminant colour temp %dK\n", colour_temp); span_log(logging, SPAN_LOG_FLOW, "Illuminant colour temp %dK\n", colour_temp);
return; return;
} }
for (i = 0; illuminants[i].name[0]; i++) for (i = 0; illuminants[i].name[0]; i++)
{ {
if (memcmp(code, illuminants[i].tag, 4) == 0) if (memcmp(code, illuminants[i].tag, 4) == 0)
{ {
printf("Illuminant %s\n", illuminants[i].name); span_log(logging, SPAN_LOG_FLOW, "Illuminant %s\n", illuminants[i].name);
set_lab_illuminant(s, illuminants[i].xn, illuminants[i].yn, illuminants[i].zn); set_lab_illuminant(s, illuminants[i].xn, illuminants[i].yn, illuminants[i].zn);
break; break;
} }
} }
if (illuminants[i].name[0] == '\0') if (illuminants[i].name[0] == '\0')
printf("Unrecognised illuminant 0x%x 0x%x 0x%x 0x%x\n", code[0], code[1], code[2], code[3]); 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]);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) set_gamut_from_code(lab_params_t *s, const uint8_t code[12]) void set_gamut_from_code(logging_state_t *logging, lab_params_t *s, const uint8_t code[12])
{ {
int i; int i;
int val[6]; int val[6];
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
val[i] = pack_16(&code[2*i]); val[i] = pack_16(&code[2*i]);
printf("Gamut L=[%d,%d], a*=[%d,%d], b*=[%d,%d]\n", span_log(logging,
SPAN_LOG_FLOW,
"Gamut L=[%d,%d], a*=[%d,%d], b*=[%d,%d]\n",
val[0], val[0],
val[1], val[1],
val[2], val[2],
@ -240,7 +245,7 @@ SPAN_DECLARE(void) set_gamut_from_code(lab_params_t *s, const uint8_t code[12])
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static int isITUfax(lab_params_t *s, jpeg_saved_marker_ptr ptr) static int is_itu_fax(logging_state_t *logging, lab_params_t *s, jpeg_saved_marker_ptr ptr)
{ {
const uint8_t *data; const uint8_t *data;
int ok; int ok;
@ -252,6 +257,11 @@ static int isITUfax(lab_params_t *s, jpeg_saved_marker_ptr ptr)
{ {
if (ptr->marker == (JPEG_APP0 + 1) && ptr->data_length >= 6) if (ptr->marker == (JPEG_APP0 + 1) && ptr->data_length >= 6)
{ {
/* Markers are:
JPEG_RST0
JPEG_EOI
JPEG_APP0
JPEG_COM */
data = (const uint8_t *) ptr->data; data = (const uint8_t *) ptr->data;
if (strncmp((const char *) data, "G3FAX", 5) == 0) if (strncmp((const char *) data, "G3FAX", 5) == 0)
{ {
@ -260,29 +270,57 @@ static int isITUfax(lab_params_t *s, jpeg_saved_marker_ptr ptr)
case 0: case 0:
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
val[i] = pack_16(&data[6 + 2*i]); val[i] = pack_16(&data[6 + 2*i]);
printf("Version %d, resolution %d dpi\n", val[0], val[1]); span_log(logging, SPAN_LOG_FLOW, "Version %d, resolution %d dpi\n", val[0], val[1]);
ok = TRUE; ok = TRUE;
break; break;
case 1: case 1:
printf("Set gamut\n"); span_log(logging, SPAN_LOG_FLOW, "Set gamut\n");
set_gamut_from_code(s, &data[6]); if (ptr->data_length >= 6 + 12)
{
set_gamut_from_code(logging, s, &data[6]);
ok = TRUE; ok = TRUE;
}
else
{
span_log(logging, SPAN_LOG_FLOW, "Got bad G3FAX1 length - %d\n", ptr->data_length);
}
break; break;
case 2: case 2:
printf("Set illuminant\n"); span_log(logging, SPAN_LOG_FLOW, "Set illuminant\n");
set_illuminant_from_code(s, &data[6]); if (ptr->data_length >= 6 + 4)
{
set_illuminant_from_code(logging, s, &data[6]);
ok = TRUE; ok = TRUE;
}
else
{
span_log(logging, SPAN_LOG_FLOW, "Got bad G3FAX2 length - %d\n", ptr->data_length);
}
break; break;
case 3: case 3:
/* Colour palette table */ /* Colour palette table */
printf("Set colour palette\n"); span_log(logging, SPAN_LOG_FLOW, "Set colour palette\n");
if (ptr->data_length >= 6 + 2)
{
val[0] = pack_16(&data[6]); val[0] = pack_16(&data[6]);
printf("Colour palette %d\n", val[0]); span_log(logging, SPAN_LOG_FLOW, "Colour palette %d\n", val[0]);
}
else
{
span_log(logging, SPAN_LOG_FLOW, "Got bad G3FAX3 length - %d\n", ptr->data_length);
}
break;
default:
span_log(logging, SPAN_LOG_FLOW, "Got unexpected G3FAX%d length - %d\n", data[5], ptr->data_length);
break; break;
} }
} }
} }
else
{
span_log(logging, SPAN_LOG_FLOW, "Got marker 0x%x, length %d\n", ptr->marker, ptr->data_length);
span_log_buf(logging, SPAN_LOG_FLOW, "Got marker", (const uint8_t *) ptr->data, ptr->data_length);
}
ptr = ptr->next; ptr = ptr->next;
} }
@ -290,7 +328,7 @@ static int isITUfax(lab_params_t *s, jpeg_saved_marker_ptr ptr)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void SetITUFax(j_compress_ptr cinfo) static void set_itu_fax(j_compress_ptr cinfo)
{ {
uint8_t marker[10] = uint8_t marker[10] =
{ {
@ -358,9 +396,9 @@ SPAN_DECLARE(void) srgb_to_lab(lab_params_t *s, uint8_t lab[], const uint8_t srg
for (i = 0; i < pixels; i++) for (i = 0; i < pixels; i++)
{ {
#if defined(T42_USE_LUTS) #if defined(T42_USE_LUTS)
r = sRGB_to_linear[srgb[0]]; r = srgb_to_linear[srgb[0]];
g = sRGB_to_linear[srgb[1]]; g = srgb_to_linear[srgb[1]];
b = sRGB_to_linear[srgb[2]]; b = srgb_to_linear[srgb[2]];
#else #else
r = srgb[0]/256.0f; r = srgb[0]/256.0f;
g = srgb[1]/256.0f; g = srgb[1]/256.0f;
@ -436,11 +474,11 @@ SPAN_DECLARE(void) lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t la
#if defined(T42_USE_LUTS) #if defined(T42_USE_LUTS)
val = r*4096.0f; val = r*4096.0f;
srgb[0] = linear_to_sRGB[(val < 0) ? 0 : (val < 4095) ? val : 4095]; srgb[0] = linear_to_srgb[(val < 0) ? 0 : (val < 4095) ? val : 4095];
val = g*4096.0f; val = g*4096.0f;
srgb[1] = linear_to_sRGB[(val < 0) ? 0 : (val < 4095) ? val : 4095]; srgb[1] = linear_to_srgb[(val < 0) ? 0 : (val < 4095) ? val : 4095];
val = b*4096.0f; val = b*4096.0f;
srgb[2] = linear_to_sRGB[(val < 0) ? 0 : (val < 4095) ? val : 4095]; srgb[2] = linear_to_srgb[(val < 0) ? 0 : (val < 4095) ? val : 4095];
#else #else
/* Linear RGB to sRGB */ /* Linear RGB to sRGB */
r = (r > 0.0031308f) ? (1.055f*powf(r, 1.0f/2.4f) - 0.055f) : r*12.92f; r = (r > 0.0031308f) ? (1.055f*powf(r, 1.0f/2.4f) - 0.055f) : r*12.92f;
@ -461,54 +499,77 @@ SPAN_DECLARE(void) lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t la
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t42_itulab_to_jpeg(lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, char *emsg, size_t max_emsg_bytes) SPAN_DECLARE(int) t42_itulab_to_jpeg(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen)
{ {
struct jpeg_decompress_struct decompressor; struct jpeg_decompress_struct decompressor;
struct jpeg_compress_struct compressor; struct jpeg_compress_struct compressor;
char *outptr;
size_t outsize;
FILE *in; FILE *in;
FILE *out; FILE *out;
int m; int m;
JSAMPROW scan_line_in; JSAMPROW scan_line_in;
JSAMPROW scan_line_out; JSAMPROW scan_line_out;
escape_route_t escape; escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0'; escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM) #if defined(HAVE_OPEN_MEMSTREAM)
in = fmemopen(src, srclen, "r"); if ((in = fmemopen(src, srclen, "r")) == NULL)
#else
in = tmpfile();
fwrite(src, 1, srclen, in);
rewind(in);
#endif
if (in == NULL)
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Failed to fmemopen().\n");
strcpy(emsg, "Failed to fmemopen().");
return FALSE; return FALSE;
} }
outsize = 0;
#if defined(HAVE_OPEN_MEMSTREAM) if ((out = open_memstream(&outptr, &outsize)) == NULL)
out = open_memstream(&outptr, &outsize);
#else
out = tmpfile();
#endif
if (out == NULL)
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
strcpy(emsg, "Failed to open_memstream()."); fclose(in);
return FALSE; return FALSE;
} }
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(in);
fclose(out);
return FALSE;
}
#else
if ((in = tmpfile()) == NULL)
{
span_log(logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
return FALSE;
}
if (fwrite(src, 1, srclen, in) != srclen)
{
fclose(in);
return FALSE;
}
if (fseek(in, 0, SEEK_SET) != 0)
{
fclose(in);
return FALSE;
}
if ((out = tmpfile()) == NULL)
{
span_log(logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
fclose(in);
return FALSE;
}
#endif
scan_line_out = NULL;
if (setjmp(escape.escape)) if (setjmp(escape.escape))
{ {
strncpy(emsg, escape.error_message, max_emsg_bytes - 1); if (escape.error_message[0])
emsg[max_emsg_bytes - 1] = '\0'; span_log(logging, SPAN_LOG_FLOW, "%s\n", escape.error_message);
if (emsg[0] == '\0') else
strcpy(emsg, "Unspecified libjpeg error."); span_log(logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n");
if (scan_line_out)
free(scan_line_out);
fclose(in);
fclose(out);
return FALSE; return FALSE;
} }
@ -532,14 +593,13 @@ SPAN_DECLARE(int) t42_itulab_to_jpeg(lab_params_t *s, tdata_t *dst, tsize_t *dst
/* Take the header */ /* Take the header */
jpeg_read_header(&decompressor, TRUE); jpeg_read_header(&decompressor, TRUE);
/* Now we can force the input colorspace. For ITULab, we will use YCbCr as a "don't touch" marker */ /* Now we can force the input colour space. For ITULab, we use YCbCr as a "don't touch" marker */
decompressor.out_color_space = JCS_YCbCr; decompressor.out_color_space = JCS_YCbCr;
/* Sanity check and parameter check */ /* Sanity check and parameter check */
if (!isITUfax(s, decompressor.marker_list)) if (!is_itu_fax(logging, s, decompressor.marker_list))
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Is not an ITU FAX.\n");
strcpy(emsg, "Is not ITUFAX.");
return FALSE; return FALSE;
} }
@ -552,12 +612,13 @@ SPAN_DECLARE(int) t42_itulab_to_jpeg(lab_params_t *s, tdata_t *dst, tsize_t *dst
jpeg_create_compress(&compressor); jpeg_create_compress(&compressor);
jpeg_stdio_dest(&compressor, out); jpeg_stdio_dest(&compressor, out);
/* Force the destination color space */ /* Force the destination colour space */
compressor.in_color_space = JCS_RGB; compressor.in_color_space = JCS_RGB;
compressor.input_components = 3; compressor.input_components = 3;
jpeg_set_defaults(&compressor); jpeg_set_defaults(&compressor);
//jpeg_set_quality(&compressor, quality, TRUE /* limit to baseline-JPEG values */); /* Limit to baseline-JPEG values */
//jpeg_set_quality(&compressor, quality, TRUE);
/* Copy size, resolution, etc */ /* Copy size, resolution, etc */
jpeg_copy_critical_parameters(&decompressor, &compressor); jpeg_copy_critical_parameters(&decompressor, &compressor);
@ -592,64 +653,106 @@ SPAN_DECLARE(int) t42_itulab_to_jpeg(lab_params_t *s, tdata_t *dst, tsize_t *dst
jpeg_destroy_decompress(&decompressor); jpeg_destroy_decompress(&decompressor);
jpeg_destroy_compress(&compressor); jpeg_destroy_compress(&compressor);
fclose(in); fclose(in);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr; *dst = outptr;
*dstlen = outsize; *dstlen = outsize;
#else
*dstlen = ftell(out);
*dst = malloc(*dstlen);
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(out);
return FALSE;
}
if (fread(*dst, 1, *dstlen, out) != *dstlen)
{
free(*dst);
fclose(out);
return FALSE;
}
fclose(out);
#endif
return TRUE; return TRUE;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t42_jpeg_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, char *emsg, size_t max_emsg_bytes) SPAN_DECLARE(int) t42_jpeg_to_itulab(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen)
{ {
struct jpeg_decompress_struct decompressor; struct jpeg_decompress_struct decompressor;
struct jpeg_compress_struct compressor; struct jpeg_compress_struct compressor;
char *outptr;
size_t outsize;
FILE *in; FILE *in;
FILE *out; FILE *out;
int m; int m;
JSAMPROW scan_line_in; JSAMPROW scan_line_in;
JSAMPROW scan_line_out; JSAMPROW scan_line_out;
escape_route_t escape; escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0'; escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM) #if defined(HAVE_OPEN_MEMSTREAM)
in = fmemopen(src, srclen, "r"); if ((in = fmemopen(src, srclen, "r")) == NULL)
#else
in = tmpfile();
fwrite(src, 1, srclen, in);
rewind(in);
#endif
if (in == NULL)
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Failed to fmemopen().\n");
strcpy(emsg, "Failed to fmemopen().");
return FALSE; return FALSE;
} }
outsize = 0;
#if defined(HAVE_OPEN_MEMSTREAM) if ((out = open_memstream(&outptr, &outsize)) == NULL)
out = open_memstream(&outptr, &outsize);
#else
out = tmpfile();
#endif
if (out == NULL)
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
strcpy(emsg, "Failed to open_memstream()."); fclose(in);
return FALSE; return FALSE;
} }
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(in);
fclose(out);
return FALSE;
}
#else
if ((in = tmpfile()) == NULL)
{
span_log(logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
return FALSE;
}
if (fwrite(src, 1, srclen, in) != srclen)
{
fclose(in);
return FALSE;
}
if (fseek(in, 0, SEEK_SET) != 0)
{
fclose(in);
return FALSE;
}
if ((out = tmpfile()) == NULL)
{
span_log(logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
fclose(in);
return FALSE;
}
#endif
scan_line_out = NULL;
if (setjmp(escape.escape)) if (setjmp(escape.escape))
{ {
strncpy(emsg, escape.error_message, max_emsg_bytes - 1); if (escape.error_message[0])
emsg[max_emsg_bytes - 1] = '\0'; span_log(logging, SPAN_LOG_FLOW, "%s\n", escape.error_message);
else
span_log(logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n");
if (scan_line_out)
free(scan_line_out);
fclose(in);
fclose(out);
return FALSE; return FALSE;
} }
/* Create input decompressor. */
decompressor.err = jpeg_std_error(&error_handler); decompressor.err = jpeg_std_error(&error_handler);
decompressor.client_data = (void *) &escape; decompressor.client_data = (void *) &escape;
error_handler.error_exit = jpg_error_exit; error_handler.error_exit = jpg_error_exit;
@ -669,7 +772,7 @@ SPAN_DECLARE(int) t42_jpeg_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dst
/* Take the header */ /* Take the header */
jpeg_read_header(&decompressor, TRUE); jpeg_read_header(&decompressor, TRUE);
/* Now we can force the input colorspace. For ITULab, we will use YCbCr as a "don't touch" marker */ /* Now we can force the input colour space. For ITULab, we use YCbCr as a "don't touch" marker */
decompressor.out_color_space = JCS_RGB; decompressor.out_color_space = JCS_RGB;
compressor.err = jpeg_std_error(&error_handler); compressor.err = jpeg_std_error(&error_handler);
@ -680,12 +783,13 @@ SPAN_DECLARE(int) t42_jpeg_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dst
jpeg_create_compress(&compressor); jpeg_create_compress(&compressor);
jpeg_stdio_dest(&compressor, out); jpeg_stdio_dest(&compressor, out);
/* Force the destination color space */ /* Force the destination colour space */
compressor.in_color_space = JCS_YCbCr; compressor.in_color_space = JCS_YCbCr;
compressor.input_components = 3; compressor.input_components = 3;
jpeg_set_defaults(&compressor); jpeg_set_defaults(&compressor);
//jpeg_set_quality(&compressor, quality, TRUE /* limit to baseline-JPEG values */); /* Limit to baseline-JPEG values */
//jpeg_set_quality(&compressor, quality, TRUE);
jpeg_copy_critical_parameters(&decompressor, &compressor); jpeg_copy_critical_parameters(&decompressor, &compressor);
@ -697,7 +801,7 @@ SPAN_DECLARE(int) t42_jpeg_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dst
jpeg_start_decompress(&decompressor); jpeg_start_decompress(&decompressor);
jpeg_start_compress(&compressor, TRUE); jpeg_start_compress(&compressor, TRUE);
SetITUFax(&compressor); set_itu_fax(&compressor);
if ((scan_line_in = (JSAMPROW) malloc(decompressor.output_width*decompressor.num_components)) == NULL) if ((scan_line_in = (JSAMPROW) malloc(decompressor.output_width*decompressor.num_components)) == NULL)
return FALSE; return FALSE;
@ -722,45 +826,77 @@ SPAN_DECLARE(int) t42_jpeg_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dst
jpeg_destroy_decompress(&decompressor); jpeg_destroy_decompress(&decompressor);
jpeg_destroy_compress(&compressor); jpeg_destroy_compress(&compressor);
fclose(in); fclose(in);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr; *dst = outptr;
*dstlen = outsize; *dstlen = outsize;
#else
*dstlen = ftell(out);
*dst = malloc(*dstlen);
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(out);
return FALSE;
}
if (fread(*dst, 1, *dstlen, out) != *dstlen)
{
free(*dst);
fclose(out);
return FALSE;
}
fclose(out);
#endif
return TRUE; return TRUE;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t42_srgb_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height, char *emsg, size_t max_emsg_bytes) SPAN_DECLARE(int) t42_srgb_to_itulab(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height)
{ {
struct jpeg_compress_struct compressor; struct jpeg_compress_struct compressor;
FILE *out; FILE *out;
char *outptr;
size_t outsize;
JSAMPROW scan_line_out; JSAMPROW scan_line_out;
JSAMPROW scan_line_in; JSAMPROW scan_line_in;
tsize_t pos; tsize_t pos;
escape_route_t escape; escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0'; escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM) #if defined(HAVE_OPEN_MEMSTREAM)
out = open_memstream(&outptr, &outsize); outsize = 0;
#else if ((out = open_memstream(&outptr, &outsize)) == NULL)
out = tmpfile();
#endif
if (out == NULL)
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
strcpy(emsg, "Failed to open_memstream().");
return FALSE; return FALSE;
} }
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(out);
return FALSE;
}
#else
if ((out = tmpfile()) == NULL)
{
span_log(logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
return FALSE;
}
#endif
scan_line_out = NULL;
if (setjmp(escape.escape)) if (setjmp(escape.escape))
{ {
strncpy(emsg, escape.error_message, max_emsg_bytes - 1); if (escape.error_message[0])
emsg[max_emsg_bytes - 1] = '\0'; span_log(logging, SPAN_LOG_FLOW, "%s\n", escape.error_message);
else
span_log(logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n");
if (scan_line_out)
free(scan_line_out);
fclose(out);
return FALSE; return FALSE;
} }
@ -772,12 +908,13 @@ SPAN_DECLARE(int) t42_srgb_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dst
jpeg_create_compress(&compressor); jpeg_create_compress(&compressor);
jpeg_stdio_dest(&compressor, out); jpeg_stdio_dest(&compressor, out);
/* Force the destination color space */ /* Force the destination colour space */
compressor.in_color_space = JCS_YCbCr; compressor.in_color_space = JCS_YCbCr;
compressor.input_components = 3; compressor.input_components = 3;
jpeg_set_defaults(&compressor); jpeg_set_defaults(&compressor);
//jpeg_set_quality(&compressor, quality, TRUE /* limit to baseline-JPEG values */); /* Limit to baseline-JPEG values */
//jpeg_set_quality(&compressor, quality, TRUE);
/* Size, resolution, etc */ /* Size, resolution, etc */
compressor.image_width = width; compressor.image_width = width;
@ -785,7 +922,7 @@ SPAN_DECLARE(int) t42_srgb_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dst
jpeg_start_compress(&compressor, TRUE); jpeg_start_compress(&compressor, TRUE);
SetITUFax(&compressor); set_itu_fax(&compressor);
if ((scan_line_out = (JSAMPROW) malloc(compressor.image_width*compressor.num_components)) == NULL) if ((scan_line_out = (JSAMPROW) malloc(compressor.image_width*compressor.num_components)) == NULL)
return FALSE; return FALSE;
@ -800,44 +937,73 @@ SPAN_DECLARE(int) t42_srgb_to_itulab(lab_params_t *s, tdata_t *dst, tsize_t *dst
free(scan_line_out); free(scan_line_out);
jpeg_finish_compress(&compressor); jpeg_finish_compress(&compressor);
jpeg_destroy_compress(&compressor); jpeg_destroy_compress(&compressor);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr; *dst = outptr;
*dstlen = outsize; *dstlen = outsize;
#else
*dstlen = ftell(out);
*dst = malloc(*dstlen);
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(out);
return FALSE;
}
if (fread(*dst, 1, *dstlen, out) != *dstlen)
{
free(*dst);
fclose(out);
return FALSE;
}
fclose(out);
#endif
return TRUE; return TRUE;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t42_itulab_to_itulab(tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height, char *emsg, size_t max_emsg_bytes) SPAN_DECLARE(int) t42_itulab_to_itulab(logging_state_t *logging, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height)
{ {
struct jpeg_compress_struct compressor; struct jpeg_compress_struct compressor;
FILE *out; FILE *out;
char *outptr;
size_t outsize;
JSAMPROW scan_line_in; JSAMPROW scan_line_in;
tsize_t pos; tsize_t pos;
escape_route_t escape; escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0'; escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM) #if defined(HAVE_OPEN_MEMSTREAM)
out = open_memstream(&outptr, &outsize); outsize = 0;
#else if ((out = open_memstream(&outptr, &outsize)) == NULL)
out = tmpfile();
#endif
if (out == NULL)
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
strcpy(emsg, "Failed to open_memstream().");
return FALSE; return FALSE;
} }
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(out);
return FALSE;
}
#else
if ((out = tmpfile()) == NULL)
{
span_log(logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
return FALSE;
}
#endif
if (setjmp(escape.escape)) if (setjmp(escape.escape))
{ {
strncpy(emsg, escape.error_message, max_emsg_bytes - 1); if (escape.error_message[0])
emsg[max_emsg_bytes - 1] = '\0'; span_log(logging, SPAN_LOG_FLOW, "%s\n", escape.error_message);
else
span_log(logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n");
fclose(out);
return FALSE; return FALSE;
} }
@ -849,12 +1015,13 @@ SPAN_DECLARE(int) t42_itulab_to_itulab(tdata_t *dst, tsize_t *dstlen, tdata_t sr
jpeg_create_compress(&compressor); jpeg_create_compress(&compressor);
jpeg_stdio_dest(&compressor, out); jpeg_stdio_dest(&compressor, out);
/* Force the destination color space */ /* Force the destination colour space */
compressor.in_color_space = JCS_YCbCr; compressor.in_color_space = JCS_YCbCr;
compressor.input_components = 3; compressor.input_components = 3;
jpeg_set_defaults(&compressor); jpeg_set_defaults(&compressor);
//jpeg_set_quality(&compressor, quality, TRUE /* limit to baseline-JPEG values */); /* Limit to baseline-JPEG values */
//jpeg_set_quality(&compressor, quality, TRUE);
/* Size, resolution, etc */ /* Size, resolution, etc */
compressor.image_width = width; compressor.image_width = width;
@ -862,7 +1029,7 @@ SPAN_DECLARE(int) t42_itulab_to_itulab(tdata_t *dst, tsize_t *dstlen, tdata_t sr
jpeg_start_compress(&compressor, TRUE); jpeg_start_compress(&compressor, TRUE);
SetITUFax(&compressor); set_itu_fax(&compressor);
for (pos = 0; pos < srclen; pos += compressor.image_width*compressor.num_components) for (pos = 0; pos < srclen; pos += compressor.image_width*compressor.num_components)
{ {
@ -872,16 +1039,33 @@ SPAN_DECLARE(int) t42_itulab_to_itulab(tdata_t *dst, tsize_t *dstlen, tdata_t sr
jpeg_finish_compress(&compressor); jpeg_finish_compress(&compressor);
jpeg_destroy_compress(&compressor); jpeg_destroy_compress(&compressor);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr; *dst = outptr;
*dstlen = outsize; *dstlen = outsize;
#else
*dstlen = ftell(out);
*dst = malloc(*dstlen);
if (fseek(out, 0, SEEK_SET) != 0)
{
fclose(out);
return FALSE;
}
if (fread(*dst, 1, *dstlen, out) != *dstlen)
{
free(*dst);
fclose(out);
return FALSE;
}
fclose(out);
#endif
return TRUE; return TRUE;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t42_itulab_to_srgb(lab_params_t *s, tdata_t dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t *width, uint32_t *height, char *emsg, size_t max_emsg_bytes) SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, tdata_t dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t *width, uint32_t *height)
{ {
struct jpeg_decompress_struct decompressor; struct jpeg_decompress_struct decompressor;
JSAMPROW scan_line_out; JSAMPROW scan_line_out;
@ -892,28 +1076,41 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(lab_params_t *s, tdata_t dst, tsize_t *dstl
escape_route_t escape; escape_route_t escape;
escape.error_message[0] = '\0'; escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM) #if defined(HAVE_OPEN_MEMSTREAM)
in = fmemopen(src, srclen, "r"); if ((in = fmemopen(src, srclen, "r")) == NULL)
#else
in = tmpfile();
fwrite(src, 1, srclen, in);
rewind(in);
#endif
if (in == NULL)
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Failed to fmemopen().\n");
strcpy(emsg, "Failed to fmemopen().");
return FALSE; return FALSE;
} }
#else
if ((in = tmpfile()) == NULL)
{
span_log(logging, SPAN_LOG_FLOW, "Failed to tmpfile().\n");
return FALSE;
}
if (fwrite(src, 1, srclen, in) != srclen)
{
fclose(in);
return FALSE;
}
if (fseek(in, 0, SEEK_SET) != 0)
{
fclose(in);
return FALSE;
}
#endif
scan_line_out = NULL;
if (setjmp(escape.escape)) if (setjmp(escape.escape))
{ {
strncpy(emsg, escape.error_message, max_emsg_bytes - 1); if (escape.error_message[0])
emsg[max_emsg_bytes - 1] = '\0'; span_log(logging, SPAN_LOG_FLOW, "%s\n", escape.error_message);
if (emsg[0] == '\0') else
strcpy(emsg, "Unspecified libjpeg error."); span_log(logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n");
if (scan_line_out)
free(scan_line_out);
fclose(in);
return FALSE; return FALSE;
} }
/* Create input decompressor. */ /* Create input decompressor. */
@ -932,21 +1129,16 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(lab_params_t *s, tdata_t dst, tsize_t *dstl
/* Rewind the file */ /* Rewind the file */
if (fseek(in, 0, SEEK_SET) != 0) if (fseek(in, 0, SEEK_SET) != 0)
return FALSE; return FALSE;
printf("XXXX 10\n");
/* Take the header */ /* Take the header */
jpeg_read_header(&decompressor, FALSE); jpeg_read_header(&decompressor, FALSE);
printf("XXXX 11\n"); /* Now we can force the input colour space. For ITULab, we use YCbCr as a "don't touch" marker */
/* Now we can force the input colorspace. For ITULab, we will use YCbCr as a "don't touch" marker */
decompressor.out_color_space = JCS_YCbCr; decompressor.out_color_space = JCS_YCbCr;
printf("XXXX 12\n");
/* Sanity check and parameter check */ /* Sanity check and parameter check */
if (!isITUfax(s, decompressor.marker_list)) if (!is_itu_fax(logging, s, decompressor.marker_list))
{ {
if (emsg[0] == '\0') span_log(logging, SPAN_LOG_FLOW, "Is not an ITU FAX.\n");
strcpy(emsg, "Is not ITUFAX."); return FALSE;
//return FALSE;
} }
printf("XXXX 13\n");
/* Copy size, resolution, etc */ /* Copy size, resolution, etc */
*width = decompressor.image_width; *width = decompressor.image_width;
*height = decompressor.image_height; *height = decompressor.image_height;
@ -1030,7 +1222,7 @@ SPAN_DECLARE(uint32_t) t42_encode_get_image_length(t42_encode_state_t *s)
SPAN_DECLARE(int) t42_encode_get_compressed_image_size(t42_encode_state_t *s) SPAN_DECLARE(int) t42_encode_get_compressed_image_size(t42_encode_state_t *s)
{ {
return 0; return s->compressed_image_size;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1044,6 +1236,9 @@ SPAN_DECLARE(int) t42_encode_set_row_read_handler(t42_encode_state_t *s,
SPAN_DECLARE(int) t42_encode_restart(t42_encode_state_t *s, uint32_t image_width, uint32_t image_length) SPAN_DECLARE(int) t42_encode_restart(t42_encode_state_t *s, uint32_t image_width, uint32_t image_length)
{ {
//s->image_width = image_width;
//s->image_length = image_length;
s->compressed_image_size = 0;
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1065,6 +1260,7 @@ SPAN_DECLARE(t42_encode_state_t *) t42_encode_init(t42_encode_state_t *s,
s->row_read_handler = handler; s->row_read_handler = handler;
s->row_read_user_data = user_data; s->row_read_user_data = user_data;
t42_encode_restart(s, image_width, image_length);
return s; return s;
} }
@ -1078,7 +1274,11 @@ SPAN_DECLARE(int) t42_encode_release(t42_encode_state_t *s)
SPAN_DECLARE(int) t42_encode_free(t42_encode_state_t *s) SPAN_DECLARE(int) t42_encode_free(t42_encode_state_t *s)
{ {
return 0; int ret;
ret = t42_encode_release(s);
free(s);
return ret;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1097,6 +1297,17 @@ SPAN_DECLARE(int) t42_decode_put_chunk(t42_decode_state_t *s,
const uint8_t data[], const uint8_t data[],
size_t len) size_t len)
{ {
uint8_t *buf;
if (s->compressed_image_size + len > s->buf_size)
{
if ((buf = (uint8_t *) realloc(s->compressed_buf, s->compressed_image_size + 1000)) == NULL)
return -1;
s->buf_size = s->compressed_image_size + 1000;
s->compressed_buf = buf;
}
memcpy(&s->compressed_buf[s->compressed_image_size], data, len);
s->compressed_image_size += len;
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1105,6 +1316,8 @@ SPAN_DECLARE(int) t42_decode_set_row_write_handler(t42_decode_state_t *s,
t4_row_write_handler_t handler, t4_row_write_handler_t handler,
void *user_data) void *user_data)
{ {
s->row_write_handler = handler;
s->row_write_user_data = user_data;
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1114,6 +1327,9 @@ SPAN_DECLARE(int) t42_decode_set_comment_handler(t42_decode_state_t *s,
t4_row_write_handler_t handler, t4_row_write_handler_t handler,
void *user_data) void *user_data)
{ {
s->max_comment_len = max_comment_len;
s->comment_handler = handler;
s->comment_user_data = user_data;
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1140,7 +1356,7 @@ SPAN_DECLARE(uint32_t) t42_decode_get_image_length(t42_decode_state_t *s)
SPAN_DECLARE(int) t42_decode_get_compressed_image_size(t42_decode_state_t *s) SPAN_DECLARE(int) t42_decode_get_compressed_image_size(t42_decode_state_t *s)
{ {
return 0; return s->compressed_image_size;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1152,6 +1368,7 @@ SPAN_DECLARE(int) t42_decode_new_plane(t42_decode_state_t *s)
SPAN_DECLARE(int) t42_decode_restart(t42_decode_state_t *s) SPAN_DECLARE(int) t42_decode_restart(t42_decode_state_t *s)
{ {
s->compressed_image_size = 0;
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1172,6 +1389,11 @@ SPAN_DECLARE(t42_decode_state_t *) t42_decode_init(t42_decode_state_t *s,
s->row_write_handler = handler; s->row_write_handler = handler;
s->row_write_user_data = user_data; s->row_write_user_data = user_data;
s->buf_size = 0;
s->compressed_buf = NULL;
t42_decode_restart(s);
return s; return s;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/

View File

@ -0,0 +1,44 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* t42_t43_local.h - definitions for T.42 and T.43 shared processing
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2011 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if !defined(_T42_T43_LOCAL_H_)
#define _T42_T43_LOCAL_H_
#if defined(__cplusplus)
extern "C"
{
#endif
void set_illuminant_from_code(logging_state_t *logging, lab_params_t *s, const uint8_t code[4]);
void set_gamut_from_code(logging_state_t *logging, lab_params_t *s, const uint8_t code[12]);
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/

View File

@ -54,6 +54,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -77,6 +78,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
@ -374,7 +376,7 @@ SPAN_DECLARE(int) t4_rx_put_byte(t4_rx_state_t *s, uint8_t byte)
case T4_COMPRESSION_ITU_T85_L0: case T4_COMPRESSION_ITU_T85_L0:
return t85_decode_put_byte(&s->decoder.t85, byte); return t85_decode_put_byte(&s->decoder.t85, byte);
} }
return TRUE; return T4_DECODE_OK;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -399,7 +401,7 @@ SPAN_DECLARE(int) t4_rx_put_chunk(t4_rx_state_t *s, const uint8_t buf[], int len
case T4_COMPRESSION_ITU_T85_L0: case T4_COMPRESSION_ITU_T85_L0:
return t85_decode_put_chunk(&s->decoder.t85, buf, len); return t85_decode_put_chunk(&s->decoder.t85, buf, len);
} }
return TRUE; return T4_DECODE_OK;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/

View File

@ -85,6 +85,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -107,6 +108,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
@ -764,9 +766,9 @@ SPAN_DECLARE(int) t4_t6_decode_put_chunk(t4_t6_decode_state_t *s, const uint8_t
s->compressed_image_size += 8; s->compressed_image_size += 8;
byte = buf[i]; byte = buf[i];
if (put_bits(s, byte & 0xFF, 8)) if (put_bits(s, byte & 0xFF, 8))
return TRUE; return T4_DECODE_OK;
} }
return FALSE; return T4_DECODE_MORE_DATA;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -875,10 +877,7 @@ SPAN_DECLARE(int) t4_t6_decode_restart(t4_t6_decode_state_t *s, int image_width)
if (s->ref_runs) if (s->ref_runs)
{ {
memset(s->ref_runs, 0, run_space); memset(s->ref_runs, 0, run_space);
s->ref_runs[0] = s->ref_runs[0] = s->image_width;
s->ref_runs[1] =
s->ref_runs[2] =
s->ref_runs[3] = s->image_width;
} }
if (s->row_buf) if (s->row_buf)
memset(s->row_buf, 0, s->bytes_per_row); memset(s->row_buf, 0, s->bytes_per_row);

View File

@ -82,6 +82,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -104,6 +105,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
@ -544,6 +546,22 @@ static int row_to_run_lengths(uint32_t list[], const uint8_t row[], int width)
list[entry++] = pos; list[entry++] = pos;
} }
} }
#if defined(T4_STATE_DEBUGGING)
/* Dump the runs of black and white for analysis */
{
int prev;
int x;
printf("Runs (%d)", list[entry - 1]);
prev = 0;
for (x = 0; x < entry; x++)
{
printf(" %" PRIu32, list[x] - prev);
prev = list[x];
}
printf("\n");
}
#endif
return entry; return entry;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/

View File

@ -54,6 +54,7 @@
#include "spandsp/timezone.h" #include "spandsp/timezone.h"
#include "spandsp/t4_rx.h" #include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h" #include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h" #include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
@ -76,6 +77,7 @@
#endif #endif
#include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h" #include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h" #include "spandsp/private/t4_tx.h"
@ -180,21 +182,39 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
float y_resolution; float y_resolution;
int i; int i;
t4_tx_tiff_state_t *t; t4_tx_tiff_state_t *t;
uint16_t bits_per_sample;
uint16_t samples_per_pixel;
t = &s->tiff; t = &s->tiff;
parm16 = 0; parm16 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16); TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16);
if (parm16 != 1) bits_per_sample = parm16;
return -1;
parm16 = 0; parm16 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_SAMPLESPERPIXEL, &parm16); TIFFGetField(t->tiff_file, TIFFTAG_SAMPLESPERPIXEL, &parm16);
if (parm16 != 1) samples_per_pixel = parm16;
if (samples_per_pixel == 1 && bits_per_sample == 1)
t->image_type = T4_IMAGE_TYPE_BILEVEL;
else if (samples_per_pixel == 1 && bits_per_sample == 8)
t->image_type = T4_IMAGE_TYPE_GRAY_8BIT;
else if (samples_per_pixel == 1 && bits_per_sample > 8)
t->image_type = T4_IMAGE_TYPE_GRAY_12BIT;
else if (samples_per_pixel == 3 && bits_per_sample == 8)
t->image_type = T4_IMAGE_TYPE_COLOUR_8BIT;
else if (samples_per_pixel == 3 && bits_per_sample > 8)
t->image_type = T4_IMAGE_TYPE_COLOUR_12BIT;
else
return -1; return -1;
#if 0
/* Limit ourselves to plain black and white pages */
if (t->image_type != T4_IMAGE_TYPE_BILEVEL)
return -1;
#endif
parm32 = 0; parm32 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32); TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
s->image_width = parm32; s->image_width = parm32;
parm32 = 0; parm32 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32); TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32);
s->tiff.image_length =
s->image_length = parm32; s->image_length = parm32;
x_resolution = 0.0f; x_resolution = 0.0f;
TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution); TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);
@ -206,8 +226,6 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
TIFFGetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, &t->photo_metric); TIFFGetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, &t->photo_metric);
/* TIFFGetField(t->tiff_file, TIFFTAG_COMPRESSION, &t->????); */ /* TIFFGetField(t->tiff_file, TIFFTAG_COMPRESSION, &t->????); */
if (t->photo_metric != PHOTOMETRIC_MINISWHITE)
span_log(&s->logging, SPAN_LOG_FLOW, "%s: Photometric needs swapping.\n", s->tiff.file);
t->fill_order = FILLORDER_LSB2MSB; t->fill_order = FILLORDER_LSB2MSB;
/* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the /* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the
@ -388,52 +406,85 @@ static int open_tiff_input_file(t4_tx_state_t *s, const char *file)
static int tiff_row_read_handler(void *user_data, uint8_t buf[], size_t len) static int tiff_row_read_handler(void *user_data, uint8_t buf[], size_t len)
{ {
t4_tx_state_t *s; t4_tx_state_t *s;
int i;
s = (t4_tx_state_t *) user_data; s = (t4_tx_state_t *) user_data;
if (s->tiff.row >= s->image_length) if (s->tiff.row >= s->image_length)
return 0; return 0;
#if 0
if (TIFFReadScanline(s->tiff.tiff_file, buf, s->tiff.row, 0) < 0)
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error reading TIFF row.\n", s->tiff.file);
#else
memcpy(buf, &s->tiff.image_buffer[s->tiff.row*len], len); memcpy(buf, &s->tiff.image_buffer[s->tiff.row*len], len);
#endif
if (s->tiff.photo_metric != PHOTOMETRIC_MINISWHITE)
{
for (i = 0; i < len; i++)
buf[i] = ~buf[i];
}
if (s->tiff.fill_order != FILLORDER_LSB2MSB)
bit_reverse(buf, buf, len);
s->tiff.row++; s->tiff.row++;
return len; return len;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static int row_read(void *user_data, uint8_t buf[], size_t len)
{
t4_tx_state_t *s;
s = (t4_tx_state_t *) user_data;
if (s->tiff.raw_row >= s->tiff.image_length)
return 0;
if (TIFFReadScanline(s->tiff.tiff_file, buf, s->tiff.raw_row, 0) < 0)
return 0;
s->tiff.raw_row++;
return len;
}
/*- End of function --------------------------------------------------------*/
static int read_tiff_image(t4_tx_state_t *s) static int read_tiff_image(t4_tx_state_t *s)
{ {
int total_len; int total_len;
int len; int len;
int bytes_per_row;
int i; int i;
uint8_t *t; uint8_t *t;
image_translate_state_t *translator;
int mode;
s->image_width = 0; if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL)
TIFFGetField(s->tiff.tiff_file, TIFFTAG_IMAGEWIDTH, &s->image_width); {
s->image_length = 0; /* We need to dither this image down to pure black and white, possibly resizing it
TIFFGetField(s->tiff.tiff_file, TIFFTAG_IMAGELENGTH, &s->image_length); along the way. */
bytes_per_row = TIFFScanlineSize(s->tiff.tiff_file); if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT)
s->tiff.image_size = s->image_length*bytes_per_row; mode = IMAGE_TRANSLATE_FROM_GRAY_8;
else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT)
mode = IMAGE_TRANSLATE_FROM_GRAY_16;
else if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT)
mode = IMAGE_TRANSLATE_FROM_COLOUR_8;
else if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
mode = IMAGE_TRANSLATE_FROM_COLOUR_16;
else
return -1;
if ((translator = image_translate_init(NULL, mode, s->image_width, s->image_length, 1728, -1, row_read, s)) == NULL)
return -1;
s->image_width = image_translate_get_output_width(translator);
s->image_length = image_translate_get_output_length(translator);
s->metadata.x_resolution = T4_X_RESOLUTION_R8;
s->metadata.y_resolution = T4_Y_RESOLUTION_FINE;
s->tiff.image_size = (s->image_width*s->image_length + 7)/8;
if (s->tiff.image_size >= s->tiff.image_buffer_size) if (s->tiff.image_size >= s->tiff.image_buffer_size)
{ {
if ((t = realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL) if ((t = realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
return -1; return -1;
s->tiff.image_buffer_size += s->tiff.image_size; s->tiff.image_buffer_size = s->tiff.image_size;
s->tiff.image_buffer = t;
}
s->tiff.raw_row = 0;
total_len = 0;
for (i = 0; i < s->image_length; i++)
total_len += image_translate_row(translator, &s->tiff.image_buffer[total_len], s->image_width/8);
image_translate_free(translator);
}
else
{
s->tiff.image_size = s->image_length*TIFFScanlineSize(s->tiff.tiff_file);
if (s->tiff.image_size >= s->tiff.image_buffer_size)
{
if ((t = realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
return -1;
s->tiff.image_buffer_size = s->tiff.image_size;
s->tiff.image_buffer = t; s->tiff.image_buffer = t;
} }
#if 1
for (i = 0, total_len = 0; total_len < s->tiff.image_size; i++, total_len += len) for (i = 0, total_len = 0; total_len < s->tiff.image_size; i++, total_len += len)
{ {
if ((len = TIFFReadEncodedStrip(s->tiff.tiff_file, i, &s->tiff.image_buffer[total_len], s->tiff.image_size - total_len)) < 0) if ((len = TIFFReadEncodedStrip(s->tiff.tiff_file, i, &s->tiff.image_buffer[total_len], s->tiff.image_size - total_len)) < 0)
@ -442,7 +493,15 @@ static int read_tiff_image(t4_tx_state_t *s)
return -1; return -1;
} }
} }
#endif if (s->tiff.photo_metric != PHOTOMETRIC_MINISWHITE)
{
span_log(&s->logging, SPAN_LOG_FLOW, "%s: Photometric needs swapping.\n", s->tiff.file);
for (i = 0; i < s->tiff.image_size; i++)
s->tiff.image_buffer[i] = ~s->tiff.image_buffer[i];
}
if (s->tiff.fill_order != FILLORDER_LSB2MSB)
bit_reverse(s->tiff.image_buffer, s->tiff.image_buffer, s->tiff.image_size);
}
s->tiff.row = 0; s->tiff.row = 0;
return s->image_length; return s->image_length;
} }
@ -901,8 +960,6 @@ SPAN_DECLARE(int) t4_tx_get_chunk(t4_tx_state_t *s, uint8_t buf[], int max_len)
SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s) SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s)
{ {
uint32_t image_length;
span_log(&s->logging, SPAN_LOG_FLOW, "Start tx page %d - compression %s\n", s->current_page, t4_encoding_to_str(s->line_encoding)); span_log(&s->logging, SPAN_LOG_FLOW, "Start tx page %d - compression %s\n", s->current_page, t4_encoding_to_str(s->line_encoding));
if (s->current_page > s->stop_page) if (s->current_page > s->stop_page)
return -1; return -1;
@ -911,7 +968,7 @@ SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s)
if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page)) if (!TIFFSetDirectory(s->tiff.tiff_file, (tdir_t) s->current_page))
return -1; return -1;
get_tiff_directory_info(s); get_tiff_directory_info(s);
if ((image_length = read_tiff_image(s)) < 0) if (read_tiff_image(s) < 0)
return -1; return -1;
} }
else else

View File

@ -286,13 +286,13 @@ static int check_bih(t85_decode_state_t *s)
#endif #endif
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Fixed bytes do not contain expected values.\n"); span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Fixed bytes do not contain expected values.\n");
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
/* P - Number of bit planes */ /* P - Number of bit planes */
if (s->buffer[2] < s->min_bit_planes || s->buffer[2] > s->max_bit_planes) if (s->buffer[2] < s->min_bit_planes || s->buffer[2] > s->max_bit_planes)
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. %d bit planes. Should be %d to %d.\n", s->buffer[2], s->min_bit_planes, s->max_bit_planes); span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. %d bit planes. Should be %d to %d.\n", s->buffer[2], s->min_bit_planes, s->max_bit_planes);
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
s->bit_planes = s->buffer[2]; s->bit_planes = s->buffer[2];
s->current_bit_plane = 0; s->current_bit_plane = 0;
@ -302,38 +302,38 @@ static int check_bih(t85_decode_state_t *s)
if (s->xd == 0 || (s->max_xd && s->xd > s->max_xd)) if (s->xd == 0 || (s->max_xd && s->xd > s->max_xd))
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Width is %" PRIu32 "\n", s->xd); span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Width is %" PRIu32 "\n", s->xd);
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
/* YD - Vertical image size at layer D */ /* YD - Vertical image size at layer D */
s->yd = pack_32(&s->buffer[8]); s->yd = pack_32(&s->buffer[8]);
if (s->yd == 0 || (s->max_yd && s->yd > s->max_yd)) if (s->yd == 0 || (s->max_yd && s->yd > s->max_yd))
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Length is %" PRIu32 "\n", s->yd); span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Length is %" PRIu32 "\n", s->yd);
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
/* L0 - Rows per stripe, at the lowest resolution */ /* L0 - Rows per stripe, at the lowest resolution */
s->l0 = pack_32(&s->buffer[12]); s->l0 = pack_32(&s->buffer[12]);
if (s->l0 == 0) if (s->l0 == 0)
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. L0 is %" PRIu32 "\n", s->l0); span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. L0 is %" PRIu32 "\n", s->l0);
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
/* MX - Maximum horizontal offset allowed for AT pixel */ /* MX - Maximum horizontal offset allowed for AT pixel */
s->mx = s->buffer[16]; s->mx = s->buffer[16];
if (s->mx > 127) if (s->mx > 127)
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. MX is %d\n", s->mx); span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. MX is %d\n", s->mx);
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
/* Options byte */ /* Options byte */
s->options = s->buffer[19]; s->options = s->buffer[19];
if ((s->options & 0x97)) if ((s->options & 0x97))
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Options are 0x%X\n", s->options); span_log(&s->logging, SPAN_LOG_FLOW, "BIH invalid. Options are 0x%X\n", s->options);
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
span_log(&s->logging, SPAN_LOG_FLOW, "BIH is OK. Image is %" PRIu32 "x%" PRIu32 " pixels\n", s->xd, s->yd); span_log(&s->logging, SPAN_LOG_FLOW, "BIH is OK. Image is %" PRIu32 "x%" PRIu32 " pixels\n", s->xd, s->yd);
return T85_OK; return T4_DECODE_OK;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -368,7 +368,7 @@ SPAN_DECLARE(int) t85_decode_put_byte(t85_decode_state_t *s, int byte)
if (byte < 0) if (byte < 0)
{ {
t85_decode_rx_status(s, byte); t85_decode_rx_status(s, byte);
return (s->y >= s->yd) ? T85_OK : T85_MORE_DATA; return (s->y >= s->yd) ? T4_DECODE_OK : T4_DECODE_MORE_DATA;
} }
data[0] = byte; data[0] = byte;
return t85_decode_put_chunk(s, data, 1); return t85_decode_put_chunk(s, data, 1);
@ -399,8 +399,8 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
s->bie_len += i; s->bie_len += i;
cnt = i; cnt = i;
if (s->bie_len < 20) if (s->bie_len < 20)
return T85_MORE_DATA; return T4_DECODE_MORE_DATA;
if ((ret = check_bih(s)) != T85_OK) if ((ret = check_bih(s)) != T4_DECODE_OK)
return ret; return ret;
/* Set up the two/three row buffer */ /* Set up the two/three row buffer */
bytes_per_row = (s->xd + 7) >> 3; bytes_per_row = (s->xd + 7) >> 3;
@ -409,7 +409,7 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
{ {
/* We need to expand the 3 row buffer */ /* We need to expand the 3 row buffer */
if ((buf = (uint8_t *) realloc(s->row_buf, min_len)) == NULL) if ((buf = (uint8_t *) realloc(s->row_buf, min_len)) == NULL)
return T85_NOMEM; return T4_DECODE_NOMEM;
s->row_buf = buf; s->row_buf = buf;
s->row_buf_len = min_len; s->row_buf_len = min_len;
} }
@ -500,11 +500,11 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
s->buf_len = 0; s->buf_len = 0;
if (s->interrupt) if (s->interrupt)
return T85_INTERRUPT; return T4_DECODE_INTERRUPT;
break; break;
case T82_ABORT: case T82_ABORT:
s->buf_len = 0; s->buf_len = 0;
return T85_ABORTED; return T4_DECODE_ABORTED;
case T82_COMMENT: case T82_COMMENT:
s->buf_needed = 6; s->buf_needed = 6;
if (s->buf_len < 6) if (s->buf_len < 6)
@ -531,7 +531,7 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
s->buf_len = 0; s->buf_len = 0;
if (s->at_moves >= T85_ATMOVES_MAX) if (s->at_moves >= T85_ATMOVES_MAX)
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
s->at_row[s->at_moves] = pack_32(&s->buffer[2]); s->at_row[s->at_moves] = pack_32(&s->buffer[2]);
s->at_tx[s->at_moves] = s->buffer[6]; s->at_tx[s->at_moves] = s->buffer[6];
if (s->at_tx[s->at_moves] > s->mx if (s->at_tx[s->at_moves] > s->mx
@ -540,7 +540,7 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
|| ||
s->buffer[7] != 0) s->buffer[7] != 0)
{ {
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
s->at_moves++; s->at_moves++;
break; break;
@ -552,12 +552,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
s->buf_len = 0; s->buf_len = 0;
if (!(s->options & T85_VLENGTH)) if (!(s->options & T85_VLENGTH))
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
s->options &= ~T85_VLENGTH; s->options &= ~T85_VLENGTH;
y = pack_32(&s->buffer[2]); y = pack_32(&s->buffer[2]);
/* An update to the image length is not allowed to stretch it. */ /* An update to the image length is not allowed to stretch it. */
if (y > s->yd) if (y > s->yd)
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
s->yd = y; s->yd = y;
break; break;
case T82_SDNORM: case T82_SDNORM:
@ -567,12 +567,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
/* A plain SDNORM or SDRST with no peek ahead required */ /* A plain SDNORM or SDRST with no peek ahead required */
s->buf_len = 0; s->buf_len = 0;
if (finish_sde(s)) if (finish_sde(s))
return T85_INTERRUPT; return T4_DECODE_INTERRUPT;
/* Check whether this was the last SDE */ /* Check whether this was the last SDE */
if (s->y >= s->yd) if (s->y >= s->yd)
{ {
s->compressed_image_size -= (len - cnt); s->compressed_image_size -= (len - cnt);
return T85_OK; return T4_DECODE_OK;
} }
break; break;
} }
@ -594,12 +594,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
cnt--; cnt--;
/* Process the T82_SDNORM or T82_SDRST */ /* Process the T82_SDNORM or T82_SDRST */
if (finish_sde(s)) if (finish_sde(s))
return T85_INTERRUPT; return T4_DECODE_INTERRUPT;
/* Check whether this was the last SDE */ /* Check whether this was the last SDE */
if (s->y >= s->yd) if (s->y >= s->yd)
{ {
s->compressed_image_size -= (len - cnt); s->compressed_image_size -= (len - cnt);
return T85_OK; return T4_DECODE_OK;
} }
break; break;
} }
@ -613,12 +613,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
/* Process the T82_SDNORM or T82_SDRST */ /* Process the T82_SDNORM or T82_SDRST */
if (finish_sde(s)) if (finish_sde(s))
return T85_INTERRUPT; return T4_DECODE_INTERRUPT;
/* Check whether this was the last SDE */ /* Check whether this was the last SDE */
if (s->y >= s->yd) if (s->y >= s->yd)
{ {
s->compressed_image_size -= (len - cnt); s->compressed_image_size -= (len - cnt);
return T85_OK; return T4_DECODE_OK;
} }
/* Recycle the two peek-ahead marker sequence bytes to /* Recycle the two peek-ahead marker sequence bytes to
be processed later. */ be processed later. */
@ -639,12 +639,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
y = pack_32(&s->buffer[4]); y = pack_32(&s->buffer[4]);
/* An update to the image length is not allowed to stretch it. */ /* An update to the image length is not allowed to stretch it. */
if (y > s->yd) if (y > s->yd)
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
/* Things look OK, so accept this new length, and proceed. */ /* Things look OK, so accept this new length, and proceed. */
s->yd = y; s->yd = y;
/* Now process the T82_SDNORM or T82_SDRST */ /* Now process the T82_SDNORM or T82_SDRST */
if (finish_sde(s)) if (finish_sde(s))
return T85_INTERRUPT; return T4_DECODE_INTERRUPT;
/* We might be at the end of the image now, but even if we are /* We might be at the end of the image now, but even if we are
there should still be a final training T82_SDNORM or T82_SDRST there should still be a final training T82_SDNORM or T82_SDRST
that we should pick up. When we do, we won't wait for further that we should pick up. When we do, we won't wait for further
@ -653,7 +653,7 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
break; break;
default: default:
s->buf_len = 0; s->buf_len = 0;
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
} }
else if (cnt < len && data[cnt] == T82_ESC) else if (cnt < len && data[cnt] == T82_ESC)
@ -665,15 +665,15 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
/* We have found PSCD bytes */ /* We have found PSCD bytes */
cnt += decode_pscd(s, data + cnt, len - cnt); cnt += decode_pscd(s, data + cnt, len - cnt);
if (s->interrupt) if (s->interrupt)
return T85_INTERRUPT; return T4_DECODE_INTERRUPT;
/* We should only have stopped processing PSCD if /* We should only have stopped processing PSCD if
we ran out of data, or hit a T82_ESC */ we ran out of data, or hit a T82_ESC */
if (cnt < len && data[cnt] != T82_ESC) if (cnt < len && data[cnt] != T82_ESC)
return T85_INVALID_DATA; return T4_DECODE_INVALID_DATA;
} }
} }
return T85_MORE_DATA; return T4_DECODE_MORE_DATA;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/

View File

@ -213,7 +213,7 @@ static void dither_tests_gray16(void)
image[i*im.width + j] = j*1200; image[i*im.width + j] = j*1200;
} }
s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_16, im.width, im.length, -1, row_read, &im); s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_16, im.width, im.length, -1, -1, row_read, &im);
get_flattened_image(s, TRUE); get_flattened_image(s, TRUE);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -239,7 +239,7 @@ static void dither_tests_gray8(void)
for (j = 0; j < im.width; j++) for (j = 0; j < im.width; j++)
image[i*im.width + j] = j*1200/256; image[i*im.width + j] = j*1200/256;
} }
s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_8, im.width, im.length, -1, row_read, &im); s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_8, im.width, im.length, -1, -1, row_read, &im);
get_flattened_image(s, TRUE); get_flattened_image(s, TRUE);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -269,7 +269,7 @@ static void dither_tests_colour16(void)
image[i*3*im.width + 3*j + 2] = j*1200; image[i*3*im.width + 3*j + 2] = j*1200;
} }
} }
s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_16, im.width, im.length, -1, row_read, &im); s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_16, im.width, im.length, -1, -1, row_read, &im);
get_flattened_image(s, TRUE); get_flattened_image(s, TRUE);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -300,7 +300,7 @@ static void dither_tests_colour8(void)
} }
} }
s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, -1, row_read, &im); s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, -1, -1, row_read, &im);
get_flattened_image(s, TRUE); get_flattened_image(s, TRUE);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -331,13 +331,13 @@ static void grow_tests_colour8(void)
} }
} }
s1 = image_translate_init(s1, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, 200, row_read, &im); s1 = image_translate_init(s1, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, 200, -1, row_read, &im);
get_flattened_image(s1, FALSE); get_flattened_image(s1, FALSE);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void lenna_tests(int output_width, const char *file) static void lenna_tests(int output_width, int output_length_scaling, const char *file)
{ {
TIFF *in_file; TIFF *in_file;
TIFF *out_file; TIFF *out_file;
@ -355,6 +355,9 @@ static void lenna_tests(int output_width, const char *file)
image_translate_state_t bw; image_translate_state_t bw;
image_translate_state_t *s = &bw; image_translate_state_t *s = &bw;
image_descriptor_t im; image_descriptor_t im;
float x_resolution;
float y_resolution;
uint16_t res_unit;
printf("Dithering Lenna from colour to bi-level test\n"); printf("Dithering Lenna from colour to bi-level test\n");
if ((in_file = TIFFOpen(INPUT_TIFF_FILE_NAME, "r")) == NULL) if ((in_file = TIFFOpen(INPUT_TIFF_FILE_NAME, "r")) == NULL)
@ -367,11 +370,17 @@ static void lenna_tests(int output_width, const char *file)
TIFFGetField(in_file, TIFFTAG_IMAGELENGTH, &image_length); TIFFGetField(in_file, TIFFTAG_IMAGELENGTH, &image_length);
if (image_length <= 0) if (image_length <= 0)
return; return;
x_resolution = 200.0;
TIFFGetField(in_file, TIFFTAG_XRESOLUTION, &x_resolution);
y_resolution = 200.0;
TIFFGetField(in_file, TIFFTAG_YRESOLUTION, &y_resolution);
res_unit = RESUNIT_INCH;
TIFFSetField(in_file, TIFFTAG_RESOLUTIONUNIT, &res_unit);
bits_per_sample = 0; bits_per_sample = 0;
TIFFGetField(in_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample); TIFFGetField(in_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
samples_per_pixel = 0; samples_per_pixel = 0;
TIFFGetField(in_file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel); TIFFGetField(in_file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
printf("Original image is %d x %d, %d bits per sample, %d samples per pixel\n", image_width, image_length, bits_per_sample, samples_per_pixel); printf("Original image is %d x %d, %f x %f resolution, %d bits per sample, %d samples per pixel\n", image_width, image_length, x_resolution, y_resolution, bits_per_sample, samples_per_pixel);
if ((image = malloc(image_width*image_length*samples_per_pixel)) == NULL) if ((image = malloc(image_width*image_length*samples_per_pixel)) == NULL)
return; return;
for (total = 0, i = 0; i < 1000; i++) for (total = 0, i = 0; i < 1000; i++)
@ -389,13 +398,18 @@ static void lenna_tests(int output_width, const char *file)
printf("Image size %d %d\n", total, image_width*image_length*samples_per_pixel); printf("Image size %d %d\n", total, image_width*image_length*samples_per_pixel);
TIFFClose(in_file); TIFFClose(in_file);
if (output_length_scaling > 0)
output_length = (double) image_length*output_length_scaling*output_width/image_width;
else
output_length = -1;
im.image = image; im.image = image;
im.width = image_width; im.width = image_width;
im.length = image_length; im.length = image_length;
im.current_row = 0; im.current_row = 0;
im.bytes_per_pixel = samples_per_pixel; im.bytes_per_pixel = samples_per_pixel;
s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, image_width, image_length, output_width, row_read, &im); s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, image_width, image_length, output_width, output_length, row_read, &im);
output_width = image_translate_get_output_width(s); output_width = image_translate_get_output_width(s);
output_length = image_translate_get_output_length(s); output_length = image_translate_get_output_length(s);
@ -403,6 +417,11 @@ static void lenna_tests(int output_width, const char *file)
return; return;
TIFFSetField(out_file, TIFFTAG_IMAGEWIDTH, output_width); TIFFSetField(out_file, TIFFTAG_IMAGEWIDTH, output_width);
TIFFSetField(out_file, TIFFTAG_IMAGELENGTH, output_length); TIFFSetField(out_file, TIFFTAG_IMAGELENGTH, output_length);
TIFFSetField(out_file, TIFFTAG_XRESOLUTION, x_resolution);
if (output_length_scaling > 0)
y_resolution *= output_length_scaling;
TIFFSetField(out_file, TIFFTAG_YRESOLUTION, y_resolution);
TIFFSetField(out_file, TIFFTAG_RESOLUTIONUNIT, res_unit);
TIFFSetField(out_file, TIFFTAG_BITSPERSAMPLE, 1); TIFFSetField(out_file, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(out_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(out_file, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out_file, TIFFTAG_SAMPLESPERPIXEL, 1);
@ -441,9 +460,10 @@ int main(int argc, char **argv)
grow_tests_colour8(); grow_tests_colour8();
#endif #endif
#if 1 #if 1
lenna_tests(0, "lenna-bw.tif"); lenna_tests(0, 0, "lenna-bw.tif");
lenna_tests(1728, "lenna-bw-1728.tif"); lenna_tests(200, 0, "lenna-bw-200.tif");
lenna_tests(200, "lenna-bw-200.tif"); lenna_tests(1728, 0, "lenna-bw-1728.tif");
lenna_tests(1728, 2, "lenna-bw-1728-superfine.tif");
#endif #endif
printf("Tests passed.\n"); printf("Tests passed.\n");
return 0; return 0;

View File

@ -45,7 +45,8 @@
#include "spandsp.h" #include "spandsp.h"
#define IN_FILE_NAME "../test-data/itu/t24/F21_200.TIF" //#define IN_FILE_NAME "../test-data/itu/t24/F21_200.TIF"
#define IN_FILE_NAME "../test-data/itu/t24/F21B400.TIF"
#define OUT_FILE_NAME "t42_tests_receive.tif" #define OUT_FILE_NAME "t42_tests_receive.tif"
uint8_t data5[50000000]; uint8_t data5[50000000];
@ -59,55 +60,6 @@ lab_params_t lab_param;
int write_row = 0; int write_row = 0;
typedef struct
{
float L;
float a;
float b;
} cielab_t;
#if 0
static void generate_luts(void)
{
float r;
uint8_t srgb;
int i;
printf("static const float srgb_to_linear[256] =\n");
printf("{\n");
for (i = 0; i < 256; i++)
{
/* Start with "i" as the sRGB value */
r = i/256.0f;
/* sRGB to Linear RGB */
r = (r > 0.04045f) ? powf((r + 0.055f)/1.055f, 2.4f) : r/12.92f;
printf((i < 255) ? " %f,\n" : " %f\n", r);
}
printf("};\n");
printf("static const uint8_t linear_to_srgb[4096] =\n");
printf("{\n");
for (i = 0; i < 4096; i++)
{
/* Start with "i" as the linear RGB value */
/* Linear RGB to sRGB */
r = i/4096.0f;
r = (r > 0.0031308f) ? (1.055f*powf(r, 1.0f/2.4f) - 0.055f) : r*12.92f;
r = floorf(r*256.0f);
srgb = (r < 0) ? 0 : (r <= 255) ? r : 255;
printf((i < 4095) ? " %d,\n" : " %d\n", srgb);
}
printf("};\n");
}
/*- End of function --------------------------------------------------------*/
#endif
static __inline__ uint16_t pack_16(uint8_t *s) static __inline__ uint16_t pack_16(uint8_t *s)
{ {
uint16_t value; uint16_t value;
@ -159,7 +111,6 @@ static int t85_comment_handler(void *user_data, const uint8_t buf[], size_t len)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char kk[256];
TIFF *tif; TIFF *tif;
uint32_t w; uint32_t w;
uint32_t h; uint32_t h;
@ -194,18 +145,17 @@ int main(int argc, char *argv[])
uint16_t *yyya; uint16_t *yyya;
uint16_t *yyyb; uint16_t *yyyb;
uint16_t *yyyz; uint16_t *yyyz;
logging_state_t *logging;
printf("Demo of ITU/Lab library.\n"); printf("Demo of ITU/Lab library.\n");
logging = span_log_init(NULL, SPAN_LOG_FLOW, "T.42");
TIFF_FX_init(); TIFF_FX_init();
set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f); set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f);
set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE);
#if 0
generate_luts();
#endif
source_file = (argc > 1) ? argv[1] : IN_FILE_NAME; source_file = (argc > 1) ? argv[1] : IN_FILE_NAME;
/* sRGB to ITU */ /* sRGB to ITU */
if ((tif = TIFFOpen(source_file, "r")) == NULL) if ((tif = TIFFOpen(source_file, "r")) == NULL)
@ -307,6 +257,7 @@ int main(int argc, char *argv[])
printf("Unexpected compression %d\n", compression); printf("Unexpected compression %d\n", compression);
break; break;
} }
if (process_raw) if (process_raw)
{ {
nstrips = TIFFNumberOfStrips(tif); nstrips = TIFFNumberOfStrips(tif);
@ -337,7 +288,7 @@ int main(int argc, char *argv[])
t85_decode_init(&t85_dec, t85_row_write_handler, NULL); t85_decode_init(&t85_dec, t85_row_write_handler, NULL);
t85_decode_set_comment_handler(&t85_dec, 1000, t85_comment_handler, NULL); t85_decode_set_comment_handler(&t85_dec, 1000, t85_comment_handler, NULL);
result = t85_decode_put_chunk(&t85_dec, data, total_len); result = t85_decode_put_chunk(&t85_dec, data, total_len);
if (result == T85_MORE_DATA) if (result == T4_DECODE_MORE_DATA)
result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA); result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA);
len = t85_decode_get_compressed_image_size(&t85_dec); len = t85_decode_get_compressed_image_size(&t85_dec);
printf("Compressed image is %d bytes, %d rows\n", len/8, write_row); printf("Compressed image is %d bytes, %d rows\n", len/8, write_row);
@ -396,7 +347,7 @@ int main(int argc, char *argv[])
len = t85_decode_get_compressed_image_size(&t85_dec); len = t85_decode_get_compressed_image_size(&t85_dec);
printf("Compressed image is %d bytes, %d rows\n", len/8, write_row); printf("Compressed image is %d bytes, %d rows\n", len/8, write_row);
} }
if (result == T85_MORE_DATA) if (result == T4_DECODE_MORE_DATA)
{ {
printf("More\n"); printf("More\n");
result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA); result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA);
@ -435,7 +386,7 @@ int main(int argc, char *argv[])
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp"); TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp");
TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test"); TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test");
TIFFSetField(tif, TIFFTAG_DATETIME, "2011/02/03 12:30:45"); TIFFSetField(tif, TIFFTAG_DATETIME, "2012/07/03 12:30:45");
TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org"); TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org");
TIFFSetField(tif, TIFFTAG_MODEL, "spandsp"); TIFFSetField(tif, TIFFTAG_MODEL, "spandsp");
TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org"); TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org");
@ -477,9 +428,9 @@ int main(int argc, char *argv[])
{ {
printf("YYY ITULAB\n"); printf("YYY ITULAB\n");
if (!t42_itulab_to_itulab((tdata_t) &outptr, &outsize, data, off, w, h, kk, 256)) if (!t42_itulab_to_itulab(logging, (tdata_t) &outptr, &outsize, data, off, w, h))
{ {
printf("Failed to convert to ITULAB - %s\n", kk); printf("Failed to convert to ITULAB\n");
return 1; return 1;
} }
free(data); free(data);
@ -500,9 +451,9 @@ int main(int argc, char *argv[])
set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f); set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f);
set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE);
if (!t42_srgb_to_itulab(&lab_param, (tdata_t) &outptr, &outsize, data, off, w, h, kk, 256)) if (!t42_srgb_to_itulab(logging, &lab_param, (tdata_t) &outptr, &outsize, data, off, w, h))
{ {
printf("Failed to convert to ITULAB - %s\n", kk); printf("Failed to convert to ITULAB\n");
return 1; return 1;
} }
end = rdtscll(); end = rdtscll();
@ -539,7 +490,7 @@ int main(int argc, char *argv[])
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp"); TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp");
TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test"); TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test");
TIFFSetField(tif, TIFFTAG_DATETIME, "2011/02/03 12:30:45"); TIFFSetField(tif, TIFFTAG_DATETIME, "2012/07/03 12:30:45");
TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org"); TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org");
TIFFSetField(tif, TIFFTAG_MODEL, "spandsp"); TIFFSetField(tif, TIFFTAG_MODEL, "spandsp");
TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org"); TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org");
@ -564,22 +515,22 @@ int main(int argc, char *argv[])
start = rdtscll(); start = rdtscll();
data2 = NULL; data2 = NULL;
totdata = 0; totdata = 0;
t42_itulab_to_JPEG(&lab_param, (void **) &data2, &totdata, data, off, kk, 256); t42_itulab_to_jpeg(logging, &lab_param, (void **) &data2, &totdata, data, off);
end = rdtscll(); end = rdtscll();
printf("Duration %" PRIu64 "\n", end - start); printf("Duration %" PRIu64 "\n", end - start);
printf("Compressed length %d (%p)\n", totdata, data2); printf("Compressed length %d (%p)\n", totdata, data2);
if (TIFFWriteRawStrip(tif, 0, data2, totdata) < 0) if (TIFFWriteRawStrip(tif, 0, data2, totdata) < 0)
{ {
printf("Failed to convert from ITULAB - %s\n", kk); printf("Failed to convert from ITULAB\n");
return 1; return 1;
} }
free(data); free(data);
#else #else
data2 = malloc(totdata); data2 = malloc(totdata);
start = rdtscll(); start = rdtscll();
if (!t42_itulab_to_srgb(&lab_param, data2, &off, data, off, &w, &h, kk, 256)) if (!t42_itulab_to_srgb(logging, &lab_param, data2, &off, data, off, &w, &h))
{ {
printf("Failed to convert from ITULAB - %s\n", kk); printf("Failed to convert from ITULAB\n");
return 1; return 1;
} }
end = rdtscll(); end = rdtscll();

View File

@ -293,27 +293,32 @@ int main(int argc, char *argv[])
properly. */ properly. */
min_row_bits = 50; min_row_bits = 50;
block_size = 0; block_size = 0;
while ((opt = getopt(argc, argv, "126b:m:")) != -1) while ((opt = getopt(argc, argv, "b:c:m:")) != -1)
{ {
switch (opt) switch (opt)
{ {
case '1':
compression = T4_COMPRESSION_ITU_T4_1D;
compression_step = -1;
break;
case '2':
compression = T4_COMPRESSION_ITU_T4_2D;
compression_step = -1;
break;
case '6':
compression = T4_COMPRESSION_ITU_T6;
compression_step = -1;
break;
case 'b': case 'b':
block_size = atoi(optarg); block_size = atoi(optarg);
if (block_size > 1024) if (block_size > 1024)
block_size = 1024; block_size = 1024;
break; break;
case 'c':
if (strcmp(optarg, "T41D") == 0)
{
compression = T4_COMPRESSION_ITU_T4_1D;
compression_step = -1;
}
else if (strcmp(optarg, "T42D") == 0)
{
compression = T4_COMPRESSION_ITU_T4_2D;
compression_step = -1;
}
else if (strcmp(optarg, "T6") == 0)
{
compression = T4_COMPRESSION_ITU_T6;
compression_step = -1;
}
break;
case 'm': case 'm':
min_row_bits = atoi(optarg); min_row_bits = atoi(optarg);
break; break;

View File

@ -542,7 +542,7 @@ int main(int argc, char *argv[])
#if 1 #if 1
printf("Testing image_function->compress->decompress->image_function\n"); printf("Testing image_function->compress->decompress->image_function\n");
/* Send end gets image from a function */ /* Send end gets image from a function */
if (t4_tx_init(&send_state, FALSE, -1, -1) == NULL) if (t4_tx_init(&send_state, NULL, -1, -1) == NULL)
{ {
printf("Failed to init T.4 tx\n"); printf("Failed to init T.4 tx\n");
exit(2); exit(2);
@ -680,9 +680,6 @@ int main(int argc, char *argv[])
exit(2); exit(2);
} }
span_log_set_level(&receive_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); span_log_set_level(&receive_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
t4_rx_set_x_resolution(&receive_state, t4_tx_get_x_resolution(&send_state));
t4_rx_set_y_resolution(&receive_state, t4_tx_get_y_resolution(&send_state));
t4_rx_set_image_width(&receive_state, t4_tx_get_image_width(&send_state));
/* Now send and receive all the pages in the source TIFF file */ /* Now send and receive all the pages in the source TIFF file */
sends = 0; sends = 0;
@ -725,6 +722,9 @@ int main(int argc, char *argv[])
if (t4_tx_start_page(&send_state)) if (t4_tx_start_page(&send_state))
break; break;
t4_rx_set_x_resolution(&receive_state, t4_tx_get_x_resolution(&send_state));
t4_rx_set_y_resolution(&receive_state, t4_tx_get_y_resolution(&send_state));
t4_rx_set_image_width(&receive_state, t4_tx_get_image_width(&send_state));
} }
t4_rx_start_page(&receive_state); t4_rx_start_page(&receive_state);
detect_page_end(-1000000, compression); detect_page_end(-1000000, compression);

View File

@ -262,11 +262,11 @@ static int test_cycle(const char *test_id,
t85_decode_set_comment_handler(&t85_dec, 1000, comment_handler, NULL); t85_decode_set_comment_handler(&t85_dec, 1000, comment_handler, NULL);
write_row = 0; write_row = 0;
result = t85_decode_put_chunk(&t85_dec, testbuf, testbuf_len); result = t85_decode_put_chunk(&t85_dec, testbuf, testbuf_len);
if (result == T85_MORE_DATA) if (result == T4_DECODE_MORE_DATA)
result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA); result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA);
cnt_a = t85_encode_get_compressed_image_size(&t85_enc); cnt_a = t85_encode_get_compressed_image_size(&t85_enc);
cnt_b = t85_decode_get_compressed_image_size(&t85_dec); cnt_b = t85_decode_get_compressed_image_size(&t85_dec);
if (cnt_a != cnt_b || cnt_a != testbuf_len*8 || result != T85_OK) if (cnt_a != cnt_b || cnt_a != testbuf_len*8 || result != T4_DECODE_OK)
{ {
printf("Decode result %d\n", result); printf("Decode result %d\n", result);
printf("%ld/%ld bits of %ld bits of BIE read. %lu lines decoded.\n", printf("%ld/%ld bits of %ld bits of BIE read. %lu lines decoded.\n",
@ -297,19 +297,19 @@ static int test_cycle(const char *test_id,
if (comment && comment[0] != 'X') if (comment && comment[0] != 'X')
t85_decode_set_comment_handler(&t85_dec, 1000, comment_handler, NULL); t85_decode_set_comment_handler(&t85_dec, 1000, comment_handler, NULL);
write_row = 0; write_row = 0;
result = T85_MORE_DATA; result = T4_DECODE_MORE_DATA;
for (l = 0; l < testbuf_len; l++) for (l = 0; l < testbuf_len; l++)
{ {
result = t85_decode_put_chunk(&t85_dec, &testbuf[l], 1); result = t85_decode_put_chunk(&t85_dec, &testbuf[l], 1);
if (result != T85_MORE_DATA) if (result != T4_DECODE_MORE_DATA)
{ {
l++; l++;
break; break;
} }
} }
if (result == T85_MORE_DATA) if (result == T4_DECODE_MORE_DATA)
result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA); result = t85_decode_put_byte(&t85_dec, SIG_STATUS_END_OF_DATA);
if (l != testbuf_len || result != T85_OK) if (l != testbuf_len || result != T4_DECODE_OK)
{ {
printf("Decode result %d\n", result); printf("Decode result %d\n", result);
printf("%ld bytes of %ld bytes of BIE read. %lu lines decoded.\n", printf("%ld bytes of %ld bytes of BIE read. %lu lines decoded.\n",