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)
DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \
$(srcdir)/cielab_luts.h \
$(srcdir)/math_fixed_tables.h \
$(srcdir)/v17_v32bis_rx_fixed_rrc.h \
$(srcdir)/v17_v32bis_rx_floating_rrc.h \
@ -58,6 +59,7 @@ EXTRA_DIST = floating_fudge.h \
libtiff.2008.vcproj \
filter_tools.c \
make_at_dictionary.c \
make_cielab_luts.c \
make_math_fixed_tables.c \
make_modem_filter.c \
msvc/config.h \
@ -344,6 +346,7 @@ noinst_HEADERS = cielab_luts.h \
mmx_sse_decs.h \
t30_local.h \
t4_t6_decode_states.h \
t42_t43_local.h \
v17_v32bis_rx_constellation_maps.h \
v17_v32bis_tx_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
$(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
$(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
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_floating_rrc.h

View File

@ -1,32 +1,4 @@
/*
* 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] =
static const float srgb_to_linear[256] =
{
0.000000,
0.000302,
@ -168,7 +140,7 @@ static const float sRGB_to_linear[256] =
0.248036,
0.251995,
0.255990,
0.260021,
0.260022,
0.264090,
0.268196,
0.272338,
@ -267,7 +239,7 @@ static const float sRGB_to_linear[256] =
0.831396,
0.839397,
0.847443,
0.855533,
0.855534,
0.863669,
0.871850,
0.880075,
@ -285,8 +257,7 @@ static const float sRGB_to_linear[256] =
0.982319,
0.991137
};
static const uint8_t linear_to_sRGB[4096] =
static const uint8_t linear_to_srgb[4096] =
{
0,
0,
@ -4385,5 +4356,3 @@ static const uint8_t linear_to_sRGB[4096] =
255,
255
};
#endif
/*- End of file ------------------------------------------------------------*/

View File

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

View File

@ -80,9 +80,9 @@
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.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)
{
@ -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_length;
int x;
double c1;
double c2;
#if defined(SPANDSP_USE_FIXED_POINT)
int c1;
int c2;
int frac_row;
int frac_col;
#else
double c1;
double c2;
double int_part;
double frac_row;
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)
frac_row = s->raw_output_row*input_length/output_length;
frac_row = s->raw_output_row*input_length - frac_row*output_length;
frac_row = ((s->raw_output_row*256*input_length)/output_length) & 0xFF;
for (i = 0; i < output_width; i++)
{
x = i*input_width/output_width;
frac_col = x - x*output_width;
c1 = s->raw_pixel_row[0][x] + (s->raw_pixel_row[0][x + 1] - s->raw_pixel_row[0][x])*frac_col;
c2 = s->raw_pixel_row[1][x] + (s->raw_pixel_row[1][x + 1] - s->raw_pixel_row[1][x])*frac_col;
buf[i] = saturateu8(c1 + (c2 - c1)*frac_row);
x = i*256*input_width/output_width;
frac_col = x & 0xFF;
x >>= 8;
c1 = s->raw_pixel_row[0][x] + (((s->raw_pixel_row[0][x + 1] - s->raw_pixel_row[0][x])*frac_col) >> 8);
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
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_length,
int output_width,
int output_length,
t4_row_read_handler_t row_read_handler,
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_length = input_length;
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;
if ((s->resize = (output_width > 0)))
{
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)
{

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_width The width 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
will be derived automatically from this and the source image dimension, to main the
geometry of the original image.
\param output_width The width of the output image, in pixels. If this is set <= 0 the image
will not be resized.
\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
into the translation process.
\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_length,
int output_width,
int output_length,
t4_row_read_handler_t row_read_handler,
void *row_read_user_data);

View File

@ -53,6 +53,9 @@ struct t42_encode_state_s
lab_params_t lab_params;
/*! \brief The size of the compressed image, in bytes. */
int compressed_image_size;
/*! \brief Error and flow logging control */
logging_state_t logging;
};
@ -68,6 +71,8 @@ struct t42_decode_state_s
t4_row_write_handler_t comment_handler;
/*! An opaque pointer passed to comment_handler() */
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;
@ -78,6 +83,12 @@ struct t42_decode_state_s
/*! Length of data pointed to by comment */
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 */
logging_state_t logging;
};

View File

@ -54,6 +54,12 @@ typedef struct
int image_buffer_size;
/*! \brief Row counter for playing out the rows of the image. */
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;
/*!
@ -132,6 +138,8 @@ struct t4_tx_state_s
t85_encode_state_t t85;
} encoder;
image_translate_state_t translator;
/* Supporting information, like resolutions, which the backend may want. */
t4_tx_metadata_t metadata;

View File

@ -123,11 +123,11 @@ struct t85_decode_state_s
t4_row_write_handler_t comment_handler;
/*! An opaque pointer passed to comment_handler() */
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 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 */
uint32_t max_xd;
/*! 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_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_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(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(void) t42_encode_set_options(t42_encode_state_t *s,
uint32_t l0,

View File

@ -199,6 +199,23 @@ typedef enum
T4_LENGTH_1200_US_LEGAL = 0
} 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
for a single instance of a T.4 FAX compression or decompression channel.

View File

@ -53,24 +53,6 @@ enum
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 */
typedef struct t85_encode_state_s t85_encode_state_t;

View File

@ -61,6 +61,7 @@
#include "spandsp/timezone.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42)
@ -89,6 +90,7 @@
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.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);
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))
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))
// 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)
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
must be evaluated before the minimum scan row bits can be evaluated. */
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))
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);
if (s->error_correcting_mode)
{
@ -2069,41 +2073,61 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
/* 256 octets per ECM frame */
s->octets_per_ecm_frame = 256;
/* Select the compression to use. */
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->error_correcting_mode)
{
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_T85_L0_CAPABLE))
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
{
s->line_encoding = T4_COMPRESSION_ITU_T85;
if ((s->supported_compressions & T30_SUPPORT_T85_L0_COMPRESSION)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_ITU_T85_L0;
}
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;
}
else if ((s->supported_compressions & T30_SUPPORT_T6_COMPRESSION)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_ITU_T6;
}
else 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 (s->error_correcting_mode
&&
(s->supported_compressions & T30_SUPPORT_T6_COMPRESSION)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_ITU_T6;
}
else 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;
}
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))
{
@ -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)];
/* 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))
{
s->line_encoding = T4_COMPRESSION_ITU_T85_L0;

View File

@ -61,6 +61,7 @@
#include "spandsp/timezone.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42)
@ -89,6 +90,7 @@
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.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_T6_COMPRESSION
#if defined(SPANDSP_SUPPORT_T42)
| T30_SUPPORT_T42_COMPRESSION
//| T30_SUPPORT_T42_COMPRESSION
#endif
#if defined(SPANDSP_SUPPORT_T43)
| T30_SUPPORT_T43_COMPRESSION

View File

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

View File

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

View File

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

View File

@ -61,7 +61,10 @@
#define T42_USE_LUTS
#include "t42_t43_local.h"
#if defined(T42_USE_LUTS)
#include "cielab_luts.h"
#endif
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 --------------------------------------------------------*/
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 colour_temp;
@ -205,42 +208,44 @@ SPAN_DECLARE(void) set_illuminant_from_code(lab_params_t *s, const uint8_t code[
if (code[0] == 'C' && code[1] == 'T')
{
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;
}
for (i = 0; illuminants[i].name[0]; i++)
{
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);
break;
}
}
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 --------------------------------------------------------*/
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 val[6];
for (i = 0; i < 6; i++)
val[i] = pack_16(&code[2*i]);
printf("Gamut L=[%d,%d], a*=[%d,%d], b*=[%d,%d]\n",
val[0],
val[1],
val[2],
val[3],
val[4],
val[5]);
span_log(logging,
SPAN_LOG_FLOW,
"Gamut L=[%d,%d], a*=[%d,%d], b*=[%d,%d]\n",
val[0],
val[1],
val[2],
val[3],
val[4],
val[5]);
set_lab_gamut2(s, val[0], val[1], val[2], val[3], val[4], val[5]);
}
/*- 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;
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)
{
/* Markers are:
JPEG_RST0
JPEG_EOI
JPEG_APP0
JPEG_COM */
data = (const uint8_t *) ptr->data;
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:
for (i = 0; i < 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;
break;
case 1:
printf("Set gamut\n");
set_gamut_from_code(s, &data[6]);
ok = TRUE;
span_log(logging, SPAN_LOG_FLOW, "Set gamut\n");
if (ptr->data_length >= 6 + 12)
{
set_gamut_from_code(logging, s, &data[6]);
ok = TRUE;
}
else
{
span_log(logging, SPAN_LOG_FLOW, "Got bad G3FAX1 length - %d\n", ptr->data_length);
}
break;
case 2:
printf("Set illuminant\n");
set_illuminant_from_code(s, &data[6]);
ok = TRUE;
span_log(logging, SPAN_LOG_FLOW, "Set illuminant\n");
if (ptr->data_length >= 6 + 4)
{
set_illuminant_from_code(logging, s, &data[6]);
ok = TRUE;
}
else
{
span_log(logging, SPAN_LOG_FLOW, "Got bad G3FAX2 length - %d\n", ptr->data_length);
}
break;
case 3:
/* Colour palette table */
printf("Set colour palette\n");
val[0] = pack_16(&data[6]);
printf("Colour palette %d\n", val[0]);
span_log(logging, SPAN_LOG_FLOW, "Set colour palette\n");
if (ptr->data_length >= 6 + 2)
{
val[0] = pack_16(&data[6]);
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;
}
}
}
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;
}
@ -290,7 +328,7 @@ static int isITUfax(lab_params_t *s, jpeg_saved_marker_ptr ptr)
}
/*- End of function --------------------------------------------------------*/
static void SetITUFax(j_compress_ptr cinfo)
static void set_itu_fax(j_compress_ptr cinfo)
{
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++)
{
#if defined(T42_USE_LUTS)
r = sRGB_to_linear[srgb[0]];
g = sRGB_to_linear[srgb[1]];
b = sRGB_to_linear[srgb[2]];
r = srgb_to_linear[srgb[0]];
g = srgb_to_linear[srgb[1]];
b = srgb_to_linear[srgb[2]];
#else
r = srgb[0]/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)
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;
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;
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
/* Linear RGB to sRGB */
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 --------------------------------------------------------*/
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_compress_struct compressor;
char *outptr;
size_t outsize;
FILE *in;
FILE *out;
int m;
JSAMPROW scan_line_in;
JSAMPROW scan_line_out;
escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM)
in = fmemopen(src, srclen, "r");
#else
in = tmpfile();
fwrite(src, 1, srclen, in);
rewind(in);
#endif
if (in == NULL)
if ((in = fmemopen(src, srclen, "r")) == NULL)
{
if (emsg[0] == '\0')
strcpy(emsg, "Failed to fmemopen().");
span_log(logging, SPAN_LOG_FLOW, "Failed to fmemopen().\n");
return FALSE;
}
#if defined(HAVE_OPEN_MEMSTREAM)
out = open_memstream(&outptr, &outsize);
#else
out = tmpfile();
#endif
if (out == NULL)
outsize = 0;
if ((out = open_memstream(&outptr, &outsize)) == NULL)
{
if (emsg[0] == '\0')
strcpy(emsg, "Failed to open_memstream().");
span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
fclose(in);
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))
{
strncpy(emsg, escape.error_message, max_emsg_bytes - 1);
emsg[max_emsg_bytes - 1] = '\0';
if (emsg[0] == '\0')
strcpy(emsg, "Unspecified libjpeg error.");
if (escape.error_message[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;
}
@ -532,14 +593,13 @@ SPAN_DECLARE(int) t42_itulab_to_jpeg(lab_params_t *s, tdata_t *dst, tsize_t *dst
/* Take the header */
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;
/* Sanity check and parameter check */
if (!isITUfax(s, decompressor.marker_list))
if (!is_itu_fax(logging, s, decompressor.marker_list))
{
if (emsg[0] == '\0')
strcpy(emsg, "Is not ITUFAX.");
span_log(logging, SPAN_LOG_FLOW, "Is not an ITU FAX.\n");
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_stdio_dest(&compressor, out);
/* Force the destination color space */
/* Force the destination colour space */
compressor.in_color_space = JCS_RGB;
compressor.input_components = 3;
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 */
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_compress(&compressor);
fclose(in);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr;
*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;
}
/*- 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_compress_struct compressor;
char *outptr;
size_t outsize;
FILE *in;
FILE *out;
int m;
JSAMPROW scan_line_in;
JSAMPROW scan_line_out;
escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM)
in = fmemopen(src, srclen, "r");
#else
in = tmpfile();
fwrite(src, 1, srclen, in);
rewind(in);
#endif
if (in == NULL)
if ((in = fmemopen(src, srclen, "r")) == NULL)
{
if (emsg[0] == '\0')
strcpy(emsg, "Failed to fmemopen().");
span_log(logging, SPAN_LOG_FLOW, "Failed to fmemopen().\n");
return FALSE;
}
#if defined(HAVE_OPEN_MEMSTREAM)
out = open_memstream(&outptr, &outsize);
#else
out = tmpfile();
#endif
if (out == NULL)
outsize = 0;
if ((out = open_memstream(&outptr, &outsize)) == NULL)
{
if (emsg[0] == '\0')
strcpy(emsg, "Failed to open_memstream().");
span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
fclose(in);
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))
{
strncpy(emsg, escape.error_message, max_emsg_bytes - 1);
emsg[max_emsg_bytes - 1] = '\0';
if (escape.error_message[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;
}
/* Create input decompressor. */
decompressor.err = jpeg_std_error(&error_handler);
decompressor.client_data = (void *) &escape;
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 */
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;
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_stdio_dest(&compressor, out);
/* Force the destination color space */
/* Force the destination colour space */
compressor.in_color_space = JCS_YCbCr;
compressor.input_components = 3;
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);
@ -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_compress(&compressor, TRUE);
SetITUFax(&compressor);
set_itu_fax(&compressor);
if ((scan_line_in = (JSAMPROW) malloc(decompressor.output_width*decompressor.num_components)) == NULL)
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_compress(&compressor);
fclose(in);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr;
*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;
}
/*- 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;
FILE *out;
char *outptr;
size_t outsize;
JSAMPROW scan_line_out;
JSAMPROW scan_line_in;
tsize_t pos;
escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM)
out = open_memstream(&outptr, &outsize);
#else
out = tmpfile();
#endif
if (out == NULL)
outsize = 0;
if ((out = open_memstream(&outptr, &outsize)) == NULL)
{
if (emsg[0] == '\0')
strcpy(emsg, "Failed to open_memstream().");
span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
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))
{
strncpy(emsg, escape.error_message, max_emsg_bytes - 1);
emsg[max_emsg_bytes - 1] = '\0';
if (escape.error_message[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;
}
@ -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_stdio_dest(&compressor, out);
/* Force the destination color space */
/* Force the destination colour space */
compressor.in_color_space = JCS_YCbCr;
compressor.input_components = 3;
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 */
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);
SetITUFax(&compressor);
set_itu_fax(&compressor);
if ((scan_line_out = (JSAMPROW) malloc(compressor.image_width*compressor.num_components)) == NULL)
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);
jpeg_finish_compress(&compressor);
jpeg_destroy_compress(&compressor);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr;
*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;
}
/*- 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;
FILE *out;
char *outptr;
size_t outsize;
JSAMPROW scan_line_in;
tsize_t pos;
escape_route_t escape;
#if defined(HAVE_OPEN_MEMSTREAM)
char *outptr;
size_t outsize;
#endif
escape.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM)
out = open_memstream(&outptr, &outsize);
#else
out = tmpfile();
#endif
if (out == NULL)
outsize = 0;
if ((out = open_memstream(&outptr, &outsize)) == NULL)
{
if (emsg[0] == '\0')
strcpy(emsg, "Failed to open_memstream().");
span_log(logging, SPAN_LOG_FLOW, "Failed to open_memstream().\n");
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))
{
strncpy(emsg, escape.error_message, max_emsg_bytes - 1);
emsg[max_emsg_bytes - 1] = '\0';
if (escape.error_message[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;
}
@ -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_stdio_dest(&compressor, out);
/* Force the destination color space */
/* Force the destination colour space */
compressor.in_color_space = JCS_YCbCr;
compressor.input_components = 3;
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 */
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);
SetITUFax(&compressor);
set_itu_fax(&compressor);
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_destroy_compress(&compressor);
fclose(out);
#if defined(HAVE_OPEN_MEMSTREAM)
fclose(out);
*dst = outptr;
*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;
}
/*- 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;
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.error_message[0] = '\0';
emsg[0] = '\0';
#if defined(HAVE_OPEN_MEMSTREAM)
in = fmemopen(src, srclen, "r");
#else
in = tmpfile();
fwrite(src, 1, srclen, in);
rewind(in);
#endif
if (in == NULL)
if ((in = fmemopen(src, srclen, "r")) == NULL)
{
if (emsg[0] == '\0')
strcpy(emsg, "Failed to fmemopen().");
span_log(logging, SPAN_LOG_FLOW, "Failed to fmemopen().\n");
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))
{
strncpy(emsg, escape.error_message, max_emsg_bytes - 1);
emsg[max_emsg_bytes - 1] = '\0';
if (emsg[0] == '\0')
strcpy(emsg, "Unspecified libjpeg error.");
if (escape.error_message[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);
return FALSE;
}
/* 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 */
if (fseek(in, 0, SEEK_SET) != 0)
return FALSE;
printf("XXXX 10\n");
/* Take the header */
jpeg_read_header(&decompressor, FALSE);
printf("XXXX 11\n");
/* 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;
printf("XXXX 12\n");
/* Sanity check and parameter check */
if (!isITUfax(s, decompressor.marker_list))
if (!is_itu_fax(logging, s, decompressor.marker_list))
{
if (emsg[0] == '\0')
strcpy(emsg, "Is not ITUFAX.");
//return FALSE;
span_log(logging, SPAN_LOG_FLOW, "Is not an ITU FAX.\n");
return FALSE;
}
printf("XXXX 13\n");
/* Copy size, resolution, etc */
*width = decompressor.image_width;
*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)
{
return 0;
return s->compressed_image_size;
}
/*- 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)
{
//s->image_width = image_width;
//s->image_length = image_length;
s->compressed_image_size = 0;
return 0;
}
/*- 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_user_data = user_data;
t42_encode_restart(s, image_width, image_length);
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)
{
return 0;
int ret;
ret = t42_encode_release(s);
free(s);
return ret;
}
/*- End of function --------------------------------------------------------*/
@ -1097,6 +1297,17 @@ SPAN_DECLARE(int) t42_decode_put_chunk(t42_decode_state_t *s,
const uint8_t data[],
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;
}
/*- 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,
void *user_data)
{
s->row_write_handler = handler;
s->row_write_user_data = user_data;
return 0;
}
/*- 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,
void *user_data)
{
s->max_comment_len = max_comment_len;
s->comment_handler = handler;
s->comment_user_data = user_data;
return 0;
}
/*- 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)
{
return 0;
return s->compressed_image_size;
}
/*- 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)
{
s->compressed_image_size = 0;
return 0;
}
/*- 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_user_data = user_data;
s->buf_size = 0;
s->compressed_buf = NULL;
t42_decode_restart(s);
return s;
}
/*- 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/t4_rx.h"
#include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42)
@ -77,6 +78,7 @@
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.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:
return t85_decode_put_byte(&s->decoder.t85, byte);
}
return TRUE;
return T4_DECODE_OK;
}
/*- 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:
return t85_decode_put_chunk(&s->decoder.t85, buf, len);
}
return TRUE;
return T4_DECODE_OK;
}
/*- End of function --------------------------------------------------------*/

View File

@ -85,6 +85,7 @@
#include "spandsp/timezone.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42)
@ -107,6 +108,7 @@
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.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;
byte = buf[i];
if (put_bits(s, byte & 0xFF, 8))
return TRUE;
return T4_DECODE_OK;
}
return FALSE;
return T4_DECODE_MORE_DATA;
}
/*- 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)
{
memset(s->ref_runs, 0, run_space);
s->ref_runs[0] =
s->ref_runs[1] =
s->ref_runs[2] =
s->ref_runs[3] = s->image_width;
s->ref_runs[0] = s->image_width;
}
if (s->row_buf)
memset(s->row_buf, 0, s->bytes_per_row);

View File

@ -82,6 +82,7 @@
#include "spandsp/timezone.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42)
@ -104,6 +105,7 @@
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.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;
}
}
#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;
}
/*- End of function --------------------------------------------------------*/

View File

@ -54,6 +54,7 @@
#include "spandsp/timezone.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
#include "spandsp/image_translate.h"
#include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h"
#if defined(SPANDSP_SUPPORT_T42)
@ -76,6 +77,7 @@
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/image_translate.h"
#include "spandsp/private/t4_rx.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;
int i;
t4_tx_tiff_state_t *t;
uint16_t bits_per_sample;
uint16_t samples_per_pixel;
t = &s->tiff;
parm16 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16);
if (parm16 != 1)
return -1;
bits_per_sample = parm16;
parm16 = 0;
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;
#if 0
/* Limit ourselves to plain black and white pages */
if (t->image_type != T4_IMAGE_TYPE_BILEVEL)
return -1;
#endif
parm32 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
s->image_width = parm32;
parm32 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32);
s->tiff.image_length =
s->image_length = parm32;
x_resolution = 0.0f;
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_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;
/* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the
@ -388,61 +406,102 @@ 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)
{
t4_tx_state_t *s;
int i;
s = (t4_tx_state_t *) user_data;
if (s->tiff.row >= s->image_length)
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);
#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++;
return len;
}
/*- 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)
{
int total_len;
int len;
int bytes_per_row;
int i;
uint8_t *t;
image_translate_state_t *translator;
int mode;
s->image_width = 0;
TIFFGetField(s->tiff.tiff_file, TIFFTAG_IMAGEWIDTH, &s->image_width);
s->image_length = 0;
TIFFGetField(s->tiff.tiff_file, TIFFTAG_IMAGELENGTH, &s->image_length);
bytes_per_row = TIFFScanlineSize(s->tiff.tiff_file);
s->tiff.image_size = s->image_length*bytes_per_row;
if (s->tiff.image_size >= s->tiff.image_buffer_size)
if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL)
{
if ((t = realloc(s->tiff.image_buffer, s->tiff.image_size)) == NULL)
/* We need to dither this image down to pure black and white, possibly resizing it
along the way. */
if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT)
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;
s->tiff.image_buffer_size += s->tiff.image_size;
s->tiff.image_buffer = t;
}
#if 1
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 ((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)
{
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Read error.\n", s->tiff.file);
return -1;
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.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;
}
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)
{
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Read error.\n", s->tiff.file);
return -1;
}
}
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);
}
#endif
s->tiff.row = 0;
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)
{
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));
if (s->current_page > s->stop_page)
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))
return -1;
get_tiff_directory_info(s);
if ((image_length = read_tiff_image(s)) < 0)
if (read_tiff_image(s) < 0)
return -1;
}
else

View File

@ -286,13 +286,13 @@ static int check_bih(t85_decode_state_t *s)
#endif
{
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 */
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);
return T85_INVALID_DATA;
return T4_DECODE_INVALID_DATA;
}
s->bit_planes = s->buffer[2];
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))
{
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 */
s->yd = pack_32(&s->buffer[8]);
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);
return T85_INVALID_DATA;
return T4_DECODE_INVALID_DATA;
}
/* L0 - Rows per stripe, at the lowest resolution */
s->l0 = pack_32(&s->buffer[12]);
if (s->l0 == 0)
{
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 */
s->mx = s->buffer[16];
if (s->mx > 127)
{
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 */
s->options = s->buffer[19];
if ((s->options & 0x97))
{
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);
return T85_OK;
return T4_DECODE_OK;
}
/*- End of function --------------------------------------------------------*/
@ -368,7 +368,7 @@ SPAN_DECLARE(int) t85_decode_put_byte(t85_decode_state_t *s, int byte)
if (byte < 0)
{
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;
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;
cnt = i;
if (s->bie_len < 20)
return T85_MORE_DATA;
if ((ret = check_bih(s)) != T85_OK)
return T4_DECODE_MORE_DATA;
if ((ret = check_bih(s)) != T4_DECODE_OK)
return ret;
/* Set up the two/three row buffer */
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 */
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_len = min_len;
}
@ -500,11 +500,11 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
s->buf_len = 0;
if (s->interrupt)
return T85_INTERRUPT;
return T4_DECODE_INTERRUPT;
break;
case T82_ABORT:
s->buf_len = 0;
return T85_ABORTED;
return T4_DECODE_ABORTED;
case T82_COMMENT:
s->buf_needed = 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;
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_tx[s->at_moves] = s->buffer[6];
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)
{
return T85_INVALID_DATA;
return T4_DECODE_INVALID_DATA;
}
s->at_moves++;
break;
@ -552,12 +552,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
s->buf_len = 0;
if (!(s->options & T85_VLENGTH))
return T85_INVALID_DATA;
return T4_DECODE_INVALID_DATA;
s->options &= ~T85_VLENGTH;
y = pack_32(&s->buffer[2]);
/* An update to the image length is not allowed to stretch it. */
if (y > s->yd)
return T85_INVALID_DATA;
return T4_DECODE_INVALID_DATA;
s->yd = y;
break;
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 */
s->buf_len = 0;
if (finish_sde(s))
return T85_INTERRUPT;
return T4_DECODE_INTERRUPT;
/* Check whether this was the last SDE */
if (s->y >= s->yd)
{
s->compressed_image_size -= (len - cnt);
return T85_OK;
return T4_DECODE_OK;
}
break;
}
@ -594,12 +594,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
cnt--;
/* Process the T82_SDNORM or T82_SDRST */
if (finish_sde(s))
return T85_INTERRUPT;
return T4_DECODE_INTERRUPT;
/* Check whether this was the last SDE */
if (s->y >= s->yd)
{
s->compressed_image_size -= (len - cnt);
return T85_OK;
return T4_DECODE_OK;
}
break;
}
@ -613,12 +613,12 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
/* Process the T82_SDNORM or T82_SDRST */
if (finish_sde(s))
return T85_INTERRUPT;
return T4_DECODE_INTERRUPT;
/* Check whether this was the last SDE */
if (s->y >= s->yd)
{
s->compressed_image_size -= (len - cnt);
return T85_OK;
return T4_DECODE_OK;
}
/* Recycle the two peek-ahead marker sequence bytes to
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]);
/* An update to the image length is not allowed to stretch it. */
if (y > s->yd)
return T85_INVALID_DATA;
return T4_DECODE_INVALID_DATA;
/* Things look OK, so accept this new length, and proceed. */
s->yd = y;
/* Now process the T82_SDNORM or T82_SDRST */
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
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
@ -653,7 +653,7 @@ SPAN_DECLARE(int) t85_decode_put_chunk(t85_decode_state_t *s,
break;
default:
s->buf_len = 0;
return T85_INVALID_DATA;
return T4_DECODE_INVALID_DATA;
}
}
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 */
cnt += decode_pscd(s, data + cnt, len - cnt);
if (s->interrupt)
return T85_INTERRUPT;
return T4_DECODE_INTERRUPT;
/* We should only have stopped processing PSCD if
we ran out of data, or hit a 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 --------------------------------------------------------*/

View File

@ -213,7 +213,7 @@ static void dither_tests_gray16(void)
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);
}
/*- End of function --------------------------------------------------------*/
@ -239,7 +239,7 @@ static void dither_tests_gray8(void)
for (j = 0; j < im.width; j++)
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);
}
/*- End of function --------------------------------------------------------*/
@ -269,7 +269,7 @@ static void dither_tests_colour16(void)
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);
}
/*- 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);
}
/*- 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);
}
/*- 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 *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 *s = &bw;
image_descriptor_t im;
float x_resolution;
float y_resolution;
uint16_t res_unit;
printf("Dithering Lenna from colour to bi-level test\n");
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);
if (image_length <= 0)
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;
TIFFGetField(in_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
samples_per_pixel = 0;
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)
return;
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);
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.width = image_width;
im.length = image_length;
im.current_row = 0;
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_length = image_translate_get_output_length(s);
@ -403,6 +417,11 @@ static void lenna_tests(int output_width, const char *file)
return;
TIFFSetField(out_file, TIFFTAG_IMAGEWIDTH, output_width);
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_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(out_file, TIFFTAG_SAMPLESPERPIXEL, 1);
@ -441,9 +460,10 @@ int main(int argc, char **argv)
grow_tests_colour8();
#endif
#if 1
lenna_tests(0, "lenna-bw.tif");
lenna_tests(1728, "lenna-bw-1728.tif");
lenna_tests(200, "lenna-bw-200.tif");
lenna_tests(0, 0, "lenna-bw.tif");
lenna_tests(200, 0, "lenna-bw-200.tif");
lenna_tests(1728, 0, "lenna-bw-1728.tif");
lenna_tests(1728, 2, "lenna-bw-1728-superfine.tif");
#endif
printf("Tests passed.\n");
return 0;

View File

@ -45,7 +45,8 @@
#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"
uint8_t data5[50000000];
@ -59,55 +60,6 @@ lab_params_t lab_param;
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)
{
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[])
{
char kk[256];
TIFF *tif;
uint32_t w;
uint32_t h;
@ -194,18 +145,17 @@ int main(int argc, char *argv[])
uint16_t *yyya;
uint16_t *yyyb;
uint16_t *yyyz;
logging_state_t *logging;
printf("Demo of ITU/Lab library.\n");
logging = span_log_init(NULL, SPAN_LOG_FLOW, "T.42");
TIFF_FX_init();
set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f);
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;
/* sRGB to ITU */
if ((tif = TIFFOpen(source_file, "r")) == NULL)
@ -307,6 +257,7 @@ int main(int argc, char *argv[])
printf("Unexpected compression %d\n", compression);
break;
}
if (process_raw)
{
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_set_comment_handler(&t85_dec, 1000, t85_comment_handler, NULL);
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);
len = t85_decode_get_compressed_image_size(&t85_dec);
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);
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");
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_SOFTWARE, "spandsp");
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_MODEL, "spandsp");
TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org");
@ -477,9 +428,9 @@ int main(int argc, char *argv[])
{
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;
}
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_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;
}
end = rdtscll();
@ -539,7 +490,7 @@ int main(int argc, char *argv[])
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp");
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_MODEL, "spandsp");
TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org");
@ -564,22 +515,22 @@ int main(int argc, char *argv[])
start = rdtscll();
data2 = NULL;
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();
printf("Duration %" PRIu64 "\n", end - start);
printf("Compressed length %d (%p)\n", totdata, data2);
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;
}
free(data);
#else
data2 = malloc(totdata);
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;
}
end = rdtscll();

View File

@ -293,27 +293,32 @@ int main(int argc, char *argv[])
properly. */
min_row_bits = 50;
block_size = 0;
while ((opt = getopt(argc, argv, "126b:m:")) != -1)
while ((opt = getopt(argc, argv, "b:c:m:")) != -1)
{
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':
block_size = atoi(optarg);
if (block_size > 1024)
block_size = 1024;
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':
min_row_bits = atoi(optarg);
break;

View File

@ -542,7 +542,7 @@ int main(int argc, char *argv[])
#if 1
printf("Testing image_function->compress->decompress->image_function\n");
/* 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");
exit(2);
@ -680,9 +680,6 @@ int main(int argc, char *argv[])
exit(2);
}
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 */
sends = 0;
@ -725,6 +722,9 @@ int main(int argc, char *argv[])
if (t4_tx_start_page(&send_state))
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);
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);
write_row = 0;
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);
cnt_a = t85_encode_get_compressed_image_size(&t85_enc);
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("%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')
t85_decode_set_comment_handler(&t85_dec, 1000, comment_handler, NULL);
write_row = 0;
result = T85_MORE_DATA;
result = T4_DECODE_MORE_DATA;
for (l = 0; l < testbuf_len; l++)
{
result = t85_decode_put_chunk(&t85_dec, &testbuf[l], 1);
if (result != T85_MORE_DATA)
if (result != T4_DECODE_MORE_DATA)
{
l++;
break;
}
}
if (result == T85_MORE_DATA)
if (result == T4_DECODE_MORE_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("%ld bytes of %ld bytes of BIE read. %lu lines decoded.\n",