More movement towards colour FAXing

This commit is contained in:
Steve Underwood 2013-05-29 14:47:48 +08:00
parent 3519e0f4c3
commit 3ea625c6ae
19 changed files with 1309 additions and 1023 deletions

View File

@ -52,6 +52,7 @@ EXTRA_DIST = floating_fudge.h \
make_cielab_luts.c \ make_cielab_luts.c \
make_math_fixed_tables.c \ make_math_fixed_tables.c \
make_modem_filter.c \ make_modem_filter.c \
make_t43_gray_code_tables.c \
msvc/config.h \ msvc/config.h \
msvc/Download_TIFF.2005.vcproj \ msvc/Download_TIFF.2005.vcproj \
msvc/Download_TIFF.2008.vcproj \ msvc/Download_TIFF.2008.vcproj \
@ -356,6 +357,9 @@ make_math_fixed_tables$(EXEEXT): $(top_srcdir)/src/make_math_fixed_tables.c
make_modem_filter$(EXEEXT): $(top_srcdir)/src/make_modem_filter.c $(top_srcdir)/src/filter_tools.c make_modem_filter$(EXEEXT): $(top_srcdir)/src/make_modem_filter.c $(top_srcdir)/src/filter_tools.c
$(CC_FOR_BUILD) -o make_modem_filter$(EXEEXT) $(top_srcdir)/src/make_modem_filter.c $(top_srcdir)/src/filter_tools.c -DHAVE_CONFIG_H -I$(top_builddir)/src -lm $(CC_FOR_BUILD) -o make_modem_filter$(EXEEXT) $(top_srcdir)/src/make_modem_filter.c $(top_srcdir)/src/filter_tools.c -DHAVE_CONFIG_H -I$(top_builddir)/src -lm
make_t43_gray_code_tables$(EXEEXT): $(top_srcdir)/src/make_t43_gray_code_tables.c
$(CC_FOR_BUILD) -o make_t43_gray_code_tables$(EXEEXT) $(top_srcdir)/src/make_t43_gray_code_tables.c -DHAVE_CONFIG_H -I$(top_builddir)/src -lm
# We need to run make_at_dictionary, so it generates the # We need to run make_at_dictionary, so it generates the
# at_interpreter_dictionary.h file # at_interpreter_dictionary.h file
@ -384,6 +388,11 @@ t42.lo: cielab_luts.h
cielab_luts.h: make_cielab_luts$(EXEEXT) cielab_luts.h: make_cielab_luts$(EXEEXT)
./make_cielab_luts$(EXEEXT) >cielab_luts.h ./make_cielab_luts$(EXEEXT) >cielab_luts.h
t43.lo: t43_gray_code_tables.h
t43_gray_code_tables.h: make_t43_gray_code_tables$(EXEEXT)
./make_t43_gray_code_tables$(EXEEXT) >t43_gray_code_tables.h
V17_V32BIS_RX_INCL = v17_v32bis_rx_rrc.h V17_V32BIS_RX_INCL = v17_v32bis_rx_rrc.h
v17rx.$(OBJEXT): ${V17_V32BIS_RX_INCL} v17rx.$(OBJEXT): ${V17_V32BIS_RX_INCL}

View File

@ -5527,6 +5527,9 @@ SPAN_DECLARE(void) at_interpreter(at_state_t *s, const char *cmd, int len)
{ {
if ((entry = command_search(t, &matched)) <= 0) if ((entry = command_search(t, &matched)) <= 0)
break; break;
/* The following test shouldn't be needed, but let's keep it here for completeness. */
if (entry > sizeof(at_commands)/sizeof(at_commands[0]))
break;
if ((t = at_commands[entry - 1](s, t)) == NULL) if ((t = at_commands[entry - 1](s, t)) == NULL)
break; break;
if (t == (const char *) -1) if (t == (const char *) -1)

View File

@ -253,6 +253,7 @@ static int get_and_scrunch_row(image_translate_state_t *s, uint8_t buf[])
case T4_IMAGE_TYPE_COLOUR_12BIT: case T4_IMAGE_TYPE_COLOUR_12BIT:
image_gray16_to_colour16_row((uint16_t *) buf, (uint16_t *) buf, s->input_width); image_gray16_to_colour16_row((uint16_t *) buf, (uint16_t *) buf, s->input_width);
break; break;
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_8BIT: case T4_IMAGE_TYPE_COLOUR_8BIT:
image_gray16_to_colour8_row(buf, (uint16_t *) buf, s->input_width); image_gray16_to_colour8_row(buf, (uint16_t *) buf, s->input_width);
break; break;
@ -267,6 +268,7 @@ static int get_and_scrunch_row(image_translate_state_t *s, uint8_t buf[])
case T4_IMAGE_TYPE_COLOUR_12BIT: case T4_IMAGE_TYPE_COLOUR_12BIT:
image_gray8_to_colour16_row((uint16_t *) buf, buf, s->input_width); image_gray8_to_colour16_row((uint16_t *) buf, buf, s->input_width);
break; break;
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_8BIT: case T4_IMAGE_TYPE_COLOUR_8BIT:
image_gray8_to_colour8_row(buf, buf, s->input_width); image_gray8_to_colour8_row(buf, buf, s->input_width);
break; break;
@ -282,11 +284,13 @@ static int get_and_scrunch_row(image_translate_state_t *s, uint8_t buf[])
case T4_IMAGE_TYPE_GRAY_8BIT: case T4_IMAGE_TYPE_GRAY_8BIT:
image_colour16_to_gray8_row(buf, (uint16_t *) buf, s->input_width); image_colour16_to_gray8_row(buf, (uint16_t *) buf, s->input_width);
break; break;
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_8BIT: case T4_IMAGE_TYPE_COLOUR_8BIT:
image_colour16_to_colour8_row(buf, (uint16_t *) buf, s->input_width); image_colour16_to_colour8_row(buf, (uint16_t *) buf, s->input_width);
break; break;
} }
break; break;
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_8BIT: case T4_IMAGE_TYPE_COLOUR_8BIT:
switch (s->output_format) switch (s->output_format)
{ {
@ -374,6 +378,7 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
switch (s->output_format) switch (s->output_format)
{ {
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_8BIT: case T4_IMAGE_TYPE_COLOUR_8BIT:
row8[0] = s->raw_pixel_row[0]; row8[0] = s->raw_pixel_row[0];
row8[1] = s->raw_pixel_row[1]; row8[1] = s->raw_pixel_row[1];
@ -611,12 +616,14 @@ SPAN_DECLARE(int) image_translate_row(image_translate_state_t *s, uint8_t buf[],
if (s->output_row < 0) if (s->output_row < 0)
return 0; return 0;
if (s->output_format == T4_IMAGE_TYPE_BILEVEL) switch (s->output_format)
{ {
case T4_IMAGE_TYPE_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_4COLOUR_BILEVEL:
i = floyd_steinberg_dither_row(s, buf); i = floyd_steinberg_dither_row(s, buf);
} break;
else default:
{
s->output_row++; s->output_row++;
if (s->resize) if (s->resize)
{ {
@ -631,6 +638,7 @@ SPAN_DECLARE(int) image_translate_row(image_translate_state_t *s, uint8_t buf[],
if (s->output_row < 0) if (s->output_row < 0)
return 0; return 0;
i = s->output_width*s->output_bytes_per_pixel; i = s->output_width*s->output_bytes_per_pixel;
break;
} }
return i; return i;
} }
@ -656,84 +664,42 @@ SPAN_DECLARE(int) image_translate_set_row_read_handler(image_translate_state_t *
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_state_t *s, static int image_format_to_bytes_per_pixel(int image_format)
int output_format, {
int output_width, switch (image_format)
int output_length, {
int input_format, default:
int input_width, case T4_IMAGE_TYPE_BILEVEL:
int input_length, case T4_IMAGE_TYPE_GRAY_8BIT:
t4_row_read_handler_t row_read_handler, return 1;
void *row_read_user_data) case T4_IMAGE_TYPE_GRAY_12BIT:
return 2;
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_8BIT:
return 3;
case T4_IMAGE_TYPE_4COLOUR_BILEVEL:
case T4_IMAGE_TYPE_4COLOUR_8BIT:
return 4;
case T4_IMAGE_TYPE_COLOUR_12BIT:
return 6;
case T4_IMAGE_TYPE_4COLOUR_12BIT:
return 8;
}
return 1;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) image_translate_restart(image_translate_state_t *s, int input_length)
{ {
int i; int i;
int raw_row_size; int raw_row_size;
int row_size; int row_size;
if (s == NULL)
{
if ((s = (image_translate_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));
s->input_format = input_format;
s->input_width = input_width;
s->input_length = input_length; s->input_length = input_length;
if (s->resize)
s->output_format = output_format;
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; s->output_length = (s->input_length*s->output_width)/s->input_width;
}
else else
{
s->output_width = s->input_width;
s->output_length = s->input_length; s->output_length = s->input_length;
}
switch (s->input_format)
{
case T4_IMAGE_TYPE_GRAY_8BIT:
s->input_bytes_per_pixel = 1;
break;
case T4_IMAGE_TYPE_GRAY_12BIT:
s->input_bytes_per_pixel = 2;
break;
case T4_IMAGE_TYPE_COLOUR_8BIT:
s->input_bytes_per_pixel = 3;
break;
case T4_IMAGE_TYPE_COLOUR_12BIT:
s->input_bytes_per_pixel = 6;
break;
default:
s->input_bytes_per_pixel = 1;
break;
}
switch (s->output_format)
{
case T4_IMAGE_TYPE_GRAY_8BIT:
s->output_bytes_per_pixel = 1;
break;
case T4_IMAGE_TYPE_GRAY_12BIT:
s->output_bytes_per_pixel = 2;
break;
case T4_IMAGE_TYPE_COLOUR_8BIT:
s->output_bytes_per_pixel = 3;
break;
case T4_IMAGE_TYPE_COLOUR_12BIT:
s->output_bytes_per_pixel = 6;
break;
default:
s->output_bytes_per_pixel = 1;
break;
}
/* Allocate the two row buffers we need, using the space requirements we now have */ /* Allocate the two row buffers we need, using the space requirements we now have */
raw_row_size = s->input_width*s->input_bytes_per_pixel; raw_row_size = s->input_width*s->input_bytes_per_pixel;
@ -743,31 +709,79 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta
if (s->resize) if (s->resize)
{ {
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{
if (s->raw_pixel_row[i] == NULL)
{ {
if ((s->raw_pixel_row[i] = (uint8_t *) malloc(raw_row_size)) == NULL) if ((s->raw_pixel_row[i] = (uint8_t *) malloc(raw_row_size)) == NULL)
return NULL; return -1;
}
memset(s->raw_pixel_row[i], 0, raw_row_size); memset(s->raw_pixel_row[i], 0, raw_row_size);
} }
} }
if (s->output_format == T4_IMAGE_TYPE_BILEVEL) switch (s->output_format)
{ {
case T4_IMAGE_TYPE_BILEVEL:
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
case T4_IMAGE_TYPE_4COLOUR_BILEVEL:
if (s->resize) if (s->resize)
raw_row_size = row_size; raw_row_size = row_size;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{
if (s->pixel_row[i] == NULL)
{ {
if ((s->pixel_row[i] = (uint8_t *) malloc(raw_row_size)) == NULL) if ((s->pixel_row[i] = (uint8_t *) malloc(raw_row_size)) == NULL)
return NULL; return -1;
}
memset(s->pixel_row[i], 0, raw_row_size); memset(s->pixel_row[i], 0, raw_row_size);
} }
break;
} }
s->row_read_handler = row_read_handler;
s->row_read_user_data = row_read_user_data;
s->raw_input_row = 0; s->raw_input_row = 0;
s->raw_output_row = 0; s->raw_output_row = 0;
s->output_row = 0; s->output_row = 0;
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_state_t *s,
int output_format,
int output_width,
int output_length,
int input_format,
int input_width,
int input_length,
t4_row_read_handler_t row_read_handler,
void *row_read_user_data)
{
if (s == NULL)
{
if ((s = (image_translate_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));
s->row_read_handler = row_read_handler;
s->row_read_user_data = row_read_user_data;
s->input_format = input_format;
s->input_width = input_width;
s->input_length = input_length;
s->input_bytes_per_pixel = image_format_to_bytes_per_pixel(s->input_format);
s->output_format = output_format;
s->output_bytes_per_pixel = image_format_to_bytes_per_pixel(s->output_format);
s->resize = (output_width > 0);
if (s->resize)
s->output_width = output_width;
else
s->output_width = s->input_width;
if (image_translate_restart(s, input_length))
return NULL;
return s; return s;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/

View File

@ -114,3 +114,5 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -0,0 +1,104 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* make_t43_gray_code_tables.c - Generate the Gray code tables for T.43 image
* compression.
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2012 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.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <memory.h>
#include <math.h>
int main(int argc, char *argv[])
{
int i;
int j;
int gray;
int new_gray;
int restore;
printf("static const int16_t gray_code[4096] =\n{\n");
for (i = 0; i < 4096; i++)
{
gray = i & 0x800;
for (j = 10; j >= 0; j--)
{
if (((i >> (j + 1)) & 1) ^ ((i >> j) & 1))
gray |= (1 << j);
}
printf(" 0x%04x, /* 0x%04x */\n", gray, restore);
/* Now reverse the process and check we get back where we start */
restore = gray & 0x800;
for (j = 10; j >= 0; j--)
{
if (((restore >> (j + 1)) & 1) ^ ((gray >> j) & 1))
restore |= (1 << j);
}
if (i != restore)
{
printf("Ah\n");
exit(2);
}
}
printf("};\n\n");
printf("static const int16_t anti_gray_code[4096] =\n{\n");
for (i = 0; i < 4096; i++)
{
gray = i;
restore = gray & 0x800;
for (j = 10; j >= 0; j--)
{
if (((restore >> (j + 1)) & 1) ^ ((gray >> j) & 1))
restore |= (1 << j);
}
printf(" 0x%04x, /* 0x%04x */\n", restore, gray);
/* Now reverse the process and check we get back where we start */
new_gray = restore & 0x800;
for (j = 10; j >= 0; j--)
{
if (((restore >> (j + 1)) & 1) ^ ((restore >> j) & 1))
new_gray |= (1 << j);
}
if (gray != new_gray)
{
printf("Ah\n");
exit(2);
}
}
printf("};\n");
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -83,7 +83,7 @@
#include <spandsp/private/t81_t82_arith_coding.h> #include <spandsp/private/t81_t82_arith_coding.h>
#include <spandsp/private/t85.h> #include <spandsp/private/t85.h>
#include <spandsp/private/t42.h> #include <spandsp/private/t42.h>
/*#include <spandsp/private/t43.h>*/ #include <spandsp/private/t43.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

@ -48,8 +48,24 @@ extern "C"
{ {
#endif #endif
/*! \brief Convert an X0, Y0, Z0 coordinate to a colour tempature */
SPAN_DECLARE(int) xyz_to_corrected_color_temp(float *temp, float xyz[3]);
/*! \brief Convert a colour temperature to an X0, Y0, Z0 coordinate */
SPAN_DECLARE(int) colour_temp_to_xyz(float xyz[3], float temp);
/*! \brief Convert a row of 8 bit pixels from Lab to sRGB
\param s The Lab parameters context.
\param lab The output pixels
\param srgb The input pixels
\param pixel The number of pixels in the row. */
SPAN_DECLARE(void) srgb_to_lab(lab_params_t *s, uint8_t lab[], const uint8_t srgb[], int pixels); SPAN_DECLARE(void) srgb_to_lab(lab_params_t *s, uint8_t lab[], const uint8_t srgb[], int pixels);
/*! \brief Convert a row of 8 bit pixels from sRGB to Lab
\param s The Lab parameters context.
\param srgb The output pixels
\param lab The input pixels
\param pixel The number of pixels in the row. */
SPAN_DECLARE(void) lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t lab[], int pixels); SPAN_DECLARE(void) lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t lab[], int pixels);
SPAN_DECLARE(void) set_lab_illuminant(lab_params_t *s, float new_xn, float new_yn, float new_zn); SPAN_DECLARE(void) set_lab_illuminant(lab_params_t *s, float new_xn, float new_yn, float new_zn);
@ -58,6 +74,8 @@ 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) get_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(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(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(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_jpeg(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen);
@ -68,15 +86,14 @@ SPAN_DECLARE(int) t42_srgb_to_itulab(logging_state_t *logging, lab_params_t *s,
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_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, SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, uint32_t l0, int quality, int options);
uint32_t l0,
int mx,
int options);
SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width); SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width);
SPAN_DECLARE(int) t42_encode_set_image_length(t42_encode_state_t *s, uint32_t length); SPAN_DECLARE(int) t42_encode_set_image_length(t42_encode_state_t *s, uint32_t length);
SPAN_DECLARE(int) t42_encode_set_image_type(t42_encode_state_t *s, int image_type);
SPAN_DECLARE(void) t42_encode_abort(t42_encode_state_t *s); SPAN_DECLARE(void) t42_encode_abort(t42_encode_state_t *s);
SPAN_DECLARE(void) t42_encode_comment(t42_encode_state_t *s, const uint8_t comment[], size_t len); SPAN_DECLARE(void) t42_encode_comment(t42_encode_state_t *s, const uint8_t comment[], size_t len);
@ -92,11 +109,12 @@ SPAN_DECLARE(uint32_t) t42_encode_get_image_width(t42_encode_state_t *s);
SPAN_DECLARE(uint32_t) t42_encode_get_image_length(t42_encode_state_t *s); SPAN_DECLARE(uint32_t) t42_encode_get_image_length(t42_encode_state_t *s);
/*! \brief Get the size of the compressed image in bits.
\param s The T.42 context.
\return The size of the image, in bits. */
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);
SPAN_DECLARE(int) t42_encode_set_row_read_handler(t42_encode_state_t *s, SPAN_DECLARE(int) t42_encode_set_row_read_handler(t42_encode_state_t *s, t4_row_read_handler_t handler, void *user_data);
t4_row_read_handler_t handler,
void *user_data);
/*! Get the logging context associated with a T.42 encode context. /*! Get the logging context associated with a T.42 encode context.
\brief Get the logging context associated with a T.42 encode context. \brief Get the logging context associated with a T.42 encode context.
@ -163,6 +181,14 @@ 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);
/*! A maliciously constructed T.42 image could consume too much memory, and constitute
a denial of service attack on the system. This function allows constraints to be
applied.
\brief Set constraints on the received image size.
\param s The T.42 context.
\param max_xd The maximum permitted width of the full image, in pixels
\param max_yd The maximum permitted height of the full image, in pixels
\return 0 for OK */
SPAN_DECLARE(int) t42_decode_set_image_size_constraints(t42_decode_state_t *s, SPAN_DECLARE(int) t42_decode_set_image_size_constraints(t42_decode_state_t *s,
uint32_t max_xd, uint32_t max_xd,
uint32_t max_yd); uint32_t max_yd);
@ -177,6 +203,9 @@ SPAN_DECLARE(uint32_t) t42_decode_get_image_width(t42_decode_state_t *s);
\return The length of the image, in pixels. */ \return The length of the image, in pixels. */
SPAN_DECLARE(uint32_t) t42_decode_get_image_length(t42_decode_state_t *s); SPAN_DECLARE(uint32_t) t42_decode_get_image_length(t42_decode_state_t *s);
/*! \brief Get the size of the compressed image in bits.
\param s The T.42 context.
\return The size of the image, in bits. */
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);
/*! Get the logging context associated with a T.42 decode context. /*! Get the logging context associated with a T.42 decode context.
@ -185,6 +214,8 @@ SPAN_DECLARE(int) t42_decode_get_compressed_image_size(t42_decode_state_t *s);
\return A pointer to the logging context */ \return A pointer to the logging context */
SPAN_DECLARE(logging_state_t *) t42_decode_get_logging_state(t42_decode_state_t *s); SPAN_DECLARE(logging_state_t *) t42_decode_get_logging_state(t42_decode_state_t *s);
/*! \brief Restart a T.42 decode context.
\param s The T.42 context. */
SPAN_DECLARE(int) t42_decode_restart(t42_decode_state_t *s); SPAN_DECLARE(int) t42_decode_restart(t42_decode_state_t *s);
/*! \brief Prepare to decode an image in T.42 format. /*! \brief Prepare to decode an image in T.42 format.

View File

@ -68,10 +68,10 @@ SPAN_DECLARE(int) t43_encode_set_image_width(t43_encode_state_t *s, uint32_t ima
SPAN_DECLARE(int) t43_encode_set_image_length(t43_encode_state_t *s, uint32_t length); SPAN_DECLARE(int) t43_encode_set_image_length(t43_encode_state_t *s, uint32_t length);
SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s);
SPAN_DECLARE(int) t43_encode_set_image_type(t43_encode_state_t *s, int image_type); SPAN_DECLARE(int) t43_encode_set_image_type(t43_encode_state_t *s, int image_type);
SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s);
SPAN_DECLARE(void) t43_encode_comment(t43_encode_state_t *s, const uint8_t comment[], size_t len); SPAN_DECLARE(void) t43_encode_comment(t43_encode_state_t *s, const uint8_t comment[], size_t len);
/*! \brief Check if we are at the end of the current document page. /*! \brief Check if we are at the end of the current document page.

View File

@ -537,7 +537,7 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
/*! Get the short text name of a compression format. /*! Get the short text name of a compression format.
\brief Get the short text name of an encoding format. \brief Get the short text name of an encoding format.
\param encoding The encoding type. \param compression The compression type.
\return A pointer to the string. */ \return A pointer to the string. */
SPAN_DECLARE(const char *) t4_compression_to_str(int compression); SPAN_DECLARE(const char *) t4_compression_to_str(int compression);

View File

@ -114,20 +114,23 @@ SPAN_DECLARE(logging_state_t *) t4_t6_encode_get_logging_state(t4_t6_encode_stat
/*! \brief Restart a T.4 or T.6 encode context. /*! \brief Restart a T.4 or T.6 encode context.
\param s The T.4/T.6 context. \param s The T.4/T.6 context.
\param image width The image width, in pixels. \param image_width The image width, in pixels.
\param image_length The image length, in pixels. This can be set to -1, if the length is not known.
\return 0 for success, otherwise -1. */ \return 0 for success, otherwise -1. */
SPAN_DECLARE(int) t4_t6_encode_restart(t4_t6_encode_state_t *s, int image_width); SPAN_DECLARE(int) t4_t6_encode_restart(t4_t6_encode_state_t *s, int image_width, int image_length);
/*! \brief Prepare to encode an image in T.4 or T.6 format. /*! \brief Prepare to encode an image in T.4 or T.6 format.
\param s The T.4/T.6 context. \param s The T.4/T.6 context.
\param encoding The encoding mode. \param encoding The encoding mode.
\param image width The image width, in pixels. \param image_width The image width, in pixels.
\param image_length The image length, in pixels. This can be set to -1, if the length is not known.
\param handler A callback routine to handle decoded image rows. \param handler A callback routine to handle decoded image rows.
\param user_data An opaque pointer passed to handler. \param user_data An opaque pointer passed to handler.
\return A pointer to the context, or NULL if there was a problem. */ \return A pointer to the context, or NULL if there was a problem. */
SPAN_DECLARE(t4_t6_encode_state_t *) t4_t6_encode_init(t4_t6_encode_state_t *s, SPAN_DECLARE(t4_t6_encode_state_t *) t4_t6_encode_init(t4_t6_encode_state_t *s,
int encoding, int encoding,
int image_width, int image_width,
int image_length,
t4_row_read_handler_t handler, t4_row_read_handler_t handler,
void *user_data); void *user_data);

View File

@ -751,10 +751,12 @@ static uint8_t check_next_tx_step(t30_state_t *s)
more = FALSE; more = FALSE;
if (more) if (more)
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "Another document to send\n");
//if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MULTIPLE_SELECTIVE_POLLING_CAPABLE)) //if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MULTIPLE_SELECTIVE_POLLING_CAPABLE))
// return T30_EOS; // return T30_EOS;
return (s->local_interrupt_pending) ? T30_PRI_EOM : T30_EOM; return (s->local_interrupt_pending) ? T30_PRI_EOM : T30_EOM;
} }
span_log(&s->logging, SPAN_LOG_FLOW, "No more pages to send\n");
return (s->local_interrupt_pending) ? T30_PRI_EOP : T30_EOP; return (s->local_interrupt_pending) ? T30_PRI_EOP : T30_EOP;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1169,9 +1171,9 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* Ready to receive a fax will be determined separately, and this message edited. */ /* Ready to receive a fax will be determined separately, and this message edited. */
/* With no modems set we are actually selecting V.27ter fallback at 2400bps */ /* With no modems set we are actually selecting V.27ter fallback at 2400bps */
if ((s->supported_modems & T30_SUPPORT_V27TER)) if ((s->supported_modems & T30_SUPPORT_V27TER))
set_ctrl_bit(s->local_dis_dtc_frame, 12); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_MODEM_TYPE_2);
if ((s->supported_modems & T30_SUPPORT_V29)) if ((s->supported_modems & T30_SUPPORT_V29))
set_ctrl_bit(s->local_dis_dtc_frame, 11); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_MODEM_TYPE_1);
/* V.17 is only valid when combined with V.29 and V.27ter, so if we enable V.17 we force the others too. */ /* V.17 is only valid when combined with V.29 and V.27ter, so if we enable V.17 we force the others too. */
if ((s->supported_modems & T30_SUPPORT_V17)) if ((s->supported_modems & T30_SUPPORT_V17))
s->local_dis_dtc_frame[4] |= (DISBIT6 | DISBIT4 | DISBIT3); s->local_dis_dtc_frame[4] |= (DISBIT6 | DISBIT4 | DISBIT3);
@ -1359,9 +1361,11 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* No double sided printing (alternate mode) */ /* No double sided printing (alternate mode) */
/* No double sided printing (continuous mode) */ /* No double sided printing (continuous mode) */
/* No black and white mixed raster content profile */ /* No black and white mixed raster content profile */
/* No shared data memory */ /* No shared data memory */
/* No T.44 colour space */ /* No T.44 colour space */
if ((s->iaf & T30_IAF_MODE_FLOW_CONTROL)) if ((s->iaf & T30_IAF_MODE_FLOW_CONTROL))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T38_FLOW_CONTROL_CAPABLE); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T38_FLOW_CONTROL_CAPABLE);
/* No k > 4 */ /* No k > 4 */
@ -1455,27 +1459,23 @@ static int build_dcs(t30_state_t *s)
/* Select the compression to use. */ /* Select the compression to use. */
use_bilevel = TRUE; use_bilevel = TRUE;
set_ctrl_bits(s->dcs_frame, s->min_scan_time_code, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
switch (s->line_compression) switch (s->line_compression)
{ {
case T4_COMPRESSION_T4_1D: case T4_COMPRESSION_T4_1D:
/* There is nothing to set to select this encoding. */ /* There is nothing to set to select this encoding. */
set_ctrl_bits(s->dcs_frame, s->min_scan_time_code, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
break; break;
case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T4_2D:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_2D_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_2D_MODE);
set_ctrl_bits(s->dcs_frame, s->min_scan_time_code, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
break; break;
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T6_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T6_MODE);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
break; break;
case T4_COMPRESSION_T85: case T4_COMPRESSION_T85:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T85_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T85_MODE);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
break; break;
case T4_COMPRESSION_T85_L0: case T4_COMPRESSION_T85_L0:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T85_L0_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T85_L0_MODE);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
break; break;
#if defined(SPANDSP_SUPPORT_T88) #if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88: case T4_COMPRESSION_T88:
@ -1487,7 +1487,7 @@ static int build_dcs(t30_state_t *s)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT) if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
//if (???????? & T4_COMPRESSION_?????)) //if (???????? & T4_COMPRESSION_NO_SUBSAMPLING))
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING); // set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
//if (???????? & T4_COMPRESSION_?????)) //if (???????? & T4_COMPRESSION_?????))
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES); // set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES);
@ -1501,7 +1501,7 @@ static int build_dcs(t30_state_t *s)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT) if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
//if (???????? & T4_COMPRESSION_?????)) //if (???????? & T4_COMPRESSION_NO_SUBSAMPLING))
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING); // set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
use_bilevel = FALSE; use_bilevel = FALSE;
@ -1684,7 +1684,7 @@ static int build_dcs(t30_state_t *s)
|| ||
((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200))) ((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 at %ddpi x %ddpi\n", s->x_resolution, s->y_resolution);
/* No width related bits need to be set. */ /* No width related bits need to be set. */
} }
else if (((s->image_width == T4_WIDTH_200_B4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8)) else if (((s->image_width == T4_WIDTH_200_B4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
@ -1699,7 +1699,7 @@ static int build_dcs(t30_state_t *s)
{ {
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_255MM)) if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_255MM))
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4 at %ddpi x %ddpi\n", s->x_resolution, s->y_resolution);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
} }
else else
@ -1720,7 +1720,7 @@ static int build_dcs(t30_state_t *s)
{ {
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_303MM)) if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_303MM))
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3 at %ddpi x %ddpi\n", s->x_resolution, s->y_resolution);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
} }
else else
@ -1747,7 +1747,7 @@ static int build_dcs(t30_state_t *s)
return -1; return -1;
} }
/* Deal with the image length */ /* Set the image length */
/* If the other end supports unlimited length, then use that. Otherwise, if the other end supports /* If the other end supports unlimited length, then use that. Otherwise, if the other end supports
B4 use that, as its longer than the default A4 length. */ B4 use that, as its longer than the default A4 length. */
if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED)) if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
@ -1768,10 +1768,10 @@ static int build_dcs(t30_state_t *s)
if ((s->iaf & T30_IAF_MODE_CONTINUOUS_FLOW) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T38_FAX_CAPABLE)) if ((s->iaf & T30_IAF_MODE_CONTINUOUS_FLOW) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T38_FAX_CAPABLE))
{ {
/* Clear the modem type bits, in accordance with note 77 of Table 2/T.30 */ /* Clear the modem type bits, in accordance with note 77 of Table 2/T.30 */
clr_ctrl_bit(s->local_dis_dtc_frame, 11); clr_ctrl_bit(s->local_dis_dtc_frame, T30_DCS_BIT_MODEM_TYPE_1);
clr_ctrl_bit(s->local_dis_dtc_frame, 12); clr_ctrl_bit(s->local_dis_dtc_frame, T30_DCS_BIT_MODEM_TYPE_2);
clr_ctrl_bit(s->local_dis_dtc_frame, 13); clr_ctrl_bit(s->local_dis_dtc_frame, T30_DCS_BIT_MODEM_TYPE_3);
clr_ctrl_bit(s->local_dis_dtc_frame, 14); clr_ctrl_bit(s->local_dis_dtc_frame, T30_DCS_BIT_MODEM_TYPE_4);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T38_FAX_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T38_FAX_MODE);
} }
s->dcs_len = 19; s->dcs_len = 19;
@ -2013,14 +2013,16 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
/* The following treats a width field of 11 like 10, which does what note 6 of Table 2/T.30
says we should do with the invalid value 11. */
static const int widths[6][4] = static const int widths[6][4] =
{ {
{ T4_WIDTH_100_A4, T4_WIDTH_100_B4, T4_WIDTH_100_A3, -1}, /* 100/inch */ { T4_WIDTH_100_A4, T4_WIDTH_100_B4, T4_WIDTH_100_A3, T4_WIDTH_100_A3}, /* 100/inch */
{ T4_WIDTH_200_A4, T4_WIDTH_200_B4, T4_WIDTH_200_A3, -1}, /* 200/inch / R8 resolution */ { T4_WIDTH_200_A4, T4_WIDTH_200_B4, T4_WIDTH_200_A3, T4_WIDTH_200_A3}, /* 200/inch / R8 resolution */
{ T4_WIDTH_300_A4, T4_WIDTH_300_B4, T4_WIDTH_300_A3, -1}, /* 300/inch resolution */ { T4_WIDTH_300_A4, T4_WIDTH_300_B4, T4_WIDTH_300_A3, T4_WIDTH_300_A3}, /* 300/inch resolution */
{ T4_WIDTH_400_A4, T4_WIDTH_400_B4, T4_WIDTH_400_A3, -1}, /* 400/inch / R16 resolution */ { T4_WIDTH_400_A4, T4_WIDTH_400_B4, T4_WIDTH_400_A3, T4_WIDTH_400_A3}, /* 400/inch / R16 resolution */
{ T4_WIDTH_600_A4, T4_WIDTH_600_B4, T4_WIDTH_600_A3, -1}, /* 600/inch resolution */ { T4_WIDTH_600_A4, T4_WIDTH_600_B4, T4_WIDTH_600_A3, T4_WIDTH_600_A3}, /* 600/inch resolution */
{T4_WIDTH_1200_A4, T4_WIDTH_1200_B4, T4_WIDTH_1200_A3, -1} /* 1200/inch resolution */ {T4_WIDTH_1200_A4, T4_WIDTH_1200_B4, T4_WIDTH_1200_A3, T4_WIDTH_1200_A3} /* 1200/inch resolution */
}; };
uint8_t dcs_frame[T30_MAX_DIS_DTC_DCS_LEN]; uint8_t dcs_frame[T30_MAX_DIS_DTC_DCS_LEN];
int i; int i;
@ -2588,7 +2590,28 @@ static int send_cfr_sequence(t30_state_t *s, int start)
/* (CSA) CFR */ /* (CSA) CFR */
/* CFR is usually a simple frame, but can become a sequence with Internet /* CFR is usually a simple frame, but can become a sequence with Internet
FAXing. */ FAXing. */
if (start)
{
s->step = 0;
}
switch (s->step)
{
case 0:
s->step++;
if (send_csa_frame(s))
break;
/* Fall through */
case 1:
s->step++;
send_simple_frame(s, T30_CFR); send_simple_frame(s, T30_CFR);
break;
case 2:
s->step++;
shut_down_hdlc_tx(s);
break;
default:
return -1;
}
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -6291,12 +6314,7 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
} }
break; break;
case T30_STATE_F_CFR: case T30_STATE_F_CFR:
if (s->step == 0) if (send_cfr_sequence(s, FALSE))
{
shut_down_hdlc_tx(s);
s->step++;
}
else
{ {
if (s->error_correcting_mode) if (s->error_correcting_mode)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@ extern "C"
{ {
#endif #endif
void set_illuminant_from_code(logging_state_t *logging, lab_params_t *s, const uint8_t code[4]); int 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]); void set_gamut_from_code(logging_state_t *logging, lab_params_t *s, const uint8_t code[12]);

View File

@ -61,6 +61,7 @@
#include "spandsp/private/t42.h" #include "spandsp/private/t42.h"
#include "spandsp/private/t43.h" #include "spandsp/private/t43.h"
#include "t43_gray_code_tables.h"
#include "t42_t43_local.h" #include "t42_t43_local.h"
#if !defined(FALSE) #if !defined(FALSE)
@ -74,19 +75,19 @@ SPAN_DECLARE(const char *) t43_image_type_to_str(int type)
{ {
switch (type) switch (type)
{ {
case 0: case T43_IMAGE_TYPE_RGB_BILEVEL:
return "1 bit/colour image (RGB primaries)"; return "1 bit/colour image (RGB primaries)";
case 1: case T43_IMAGE_TYPE_CMY_BILEVEL:
return "1 bit/colour image (CMY primaries)"; return "1 bit/colour image (CMY primaries)";
case 2: case T43_IMAGE_TYPE_CMYK_BILEVEL:
return "1 bit/colour image (CMYK primaries)"; return "1 bit/colour image (CMYK primaries)";
case 16: case T43_IMAGE_TYPE_8BIT_COLOUR_PALETTE:
return "Palettized colour image (CIELAB 8 bits/component precision table)"; return "Palettized colour image (CIELAB 8 bits/component precision table)";
case 17: case T43_IMAGE_TYPE_12BIT_COLOUR_PALETTE:
return "Palettized colour image (CIELAB 12 bits/component precision table)"; return "Palettized colour image (CIELAB 12 bits/component precision table)";
case 32: case T43_IMAGE_TYPE_GRAY:
return "Gray-scale image (using L*)"; return "Gray-scale image (using L*)";
case 48: case T43_IMAGE_TYPE_COLOUR:
return "Continuous-tone colour image (CIELAB)"; return "Continuous-tone colour image (CIELAB)";
} }
return "???"; return "???";
@ -129,9 +130,11 @@ static __inline__ int unpack_32(uint8_t *s, uint32_t value)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_t len) static int t43_create_header(t43_encode_state_t *s, uint8_t data[], size_t len)
{ {
int pos; int pos;
int val[6];
int bytes_per_entry;
pos = 0; pos = 0;
unpack_16(data, 0xFFA8); unpack_16(data, 0xFFA8);
@ -151,7 +154,7 @@ SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_
/* JBIG coding method (0) is the only possible value here */ /* JBIG coding method (0) is the only possible value here */
data[pos] = 0; data[pos] = 0;
pos += 1; pos += 1;
data[pos] = 42; //image_type; data[pos] = s->image_type;
pos += 1; pos += 1;
data[pos] = s->bit_planes[0]; data[pos] = s->bit_planes[0];
pos += 1; pos += 1;
@ -181,38 +184,47 @@ SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_
pos += 2; pos += 2;
memcpy(&data[pos], "G3FAX\1", 6); memcpy(&data[pos], "G3FAX\1", 6);
pos += 6; pos += 6;
unpack_16(&data[pos + 0], s->lab.offset_L); get_lab_gamut2(&s->lab, &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]);
unpack_16(&data[pos + 2], s->lab.range_L); unpack_16(&data[pos + 0], val[0]);
unpack_16(&data[pos + 4], s->lab.offset_a); unpack_16(&data[pos + 2], val[1]);
unpack_16(&data[pos + 6], s->lab.range_a); unpack_16(&data[pos + 4], val[2]);
unpack_16(&data[pos + 8], s->lab.offset_b); unpack_16(&data[pos + 6], val[3]);
unpack_16(&data[pos + 10], s->lab.range_b); unpack_16(&data[pos + 8], val[4]);
unpack_16(&data[pos + 10], val[5]);
pos += 12; pos += 12;
} }
if (s->lab.x_n != 0.9638f || s->lab.y_n != 1.0f || s->lab.z_n != 0.8245f) if (memcmp(s->illuminant_code, "\0\0\0\0", 4) != 0
||
s->illuminant_colour_temperature > 0)
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX2\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX2\n");
unpack_16(&data[pos], 0xFFE1); unpack_16(&data[pos], 0xFFE1);
pos += 2; pos += 2;
unpack_16(&data[pos], 2 + 6 + 6); unpack_16(&data[pos], 2 + 6 + 4);
pos += 2; pos += 2;
memcpy(&data[pos], "G3FAX\2", 6); memcpy(&data[pos], "G3FAX\2", 6);
pos += 6; pos += 6;
unpack_16(&data[pos], 0); if (memcmp(s->illuminant_code, "\0\0\0\0", 4) != 0)
unpack_16(&data[pos + 2], 0); {
unpack_16(&data[pos + 4], 0); memcpy(&data[pos], s->illuminant_code, 4);
set_illuminant_from_code(&s->logging, &s->lab, &data[pos]); }
pos += 6; else
{
memcpy(&data[pos], "CT", 2);
unpack_16(&data[pos + 2], s->illuminant_colour_temperature);
}
pos += 4;
} }
#if 0 #if 0
if (s->colour_map) if (s->colour_map)
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX3\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX3\n");
bytes_per_entry = (table_id == 0) ? 1 : 2;
unpack_16(&data[pos], 0xFFE3); unpack_16(&data[pos], 0xFFE3);
pos += 2; pos += 2;
unpack_32(&data[pos], ???); unpack_32(&data[pos], 2 + 6 + 2 + 4 + 3*s->colour_map_entries*bytes_per_entry);
pos += 4; pos += 4;
memcpy(&data[pos], "G3FAX\3", 6); memcpy(&data[pos], "G3FAX\3", 6);
pos += 6; pos += 6;
@ -221,7 +233,7 @@ SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_
unpack_32(&data[pos], s->colour_map_entries); unpack_32(&data[pos], s->colour_map_entries);
pos += 4; pos += 4;
srgb_to_lab(&s->lab, &data[pos], s->colour_map, s->colour_map_entries); srgb_to_lab(&s->lab, &data[pos], s->colour_map, s->colour_map_entries);
pos += 3*s->colour_map_entries; pos += 3*s->colour_map_entries*bytes_per_entry;
} }
#endif #endif
@ -257,6 +269,12 @@ SPAN_DECLARE(int) t43_encode_set_image_length(t43_encode_state_t *s, uint32_t im
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t43_encode_set_image_type(t43_encode_state_t *s, int image_type)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s) SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s)
{ {
} }
@ -343,6 +361,9 @@ SPAN_DECLARE(t43_encode_state_t *) t43_encode_init(t43_encode_state_t *s,
image_length, image_length,
handler, handler,
user_data); user_data);
s->image_type = T43_IMAGE_TYPE_8BIT_COLOUR_PALETTE;
return s; return s;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -390,9 +411,11 @@ SPAN_DECLARE(void) t43_decode_rx_status(t43_decode_state_t *s, int status)
static void set_simple_colour_map(t43_decode_state_t *s, int code) static void set_simple_colour_map(t43_decode_state_t *s, int code)
{ {
int i;
switch (code) switch (code)
{ {
case 0: case T43_IMAGE_TYPE_RGB_BILEVEL:
/* Table 3/T.43 1 bit/colour image (using RGB primaries) */ /* Table 3/T.43 1 bit/colour image (using RGB primaries) */
memset(s->colour_map, 0, sizeof(s->colour_map)); memset(s->colour_map, 0, sizeof(s->colour_map));
/* Black */ /* Black */
@ -417,7 +440,7 @@ static void set_simple_colour_map(t43_decode_state_t *s, int code)
s->colour_map[3*0xE0 + 2] = 0xF0; s->colour_map[3*0xE0 + 2] = 0xF0;
s->colour_map_entries = 256; s->colour_map_entries = 256;
break; break;
case 1: case T43_IMAGE_TYPE_CMY_BILEVEL:
/* Table 2/T.43 1 bit/colour image (using CMY primaries) */ /* Table 2/T.43 1 bit/colour image (using CMY primaries) */
memset(s->colour_map, 0, sizeof(s->colour_map)); memset(s->colour_map, 0, sizeof(s->colour_map));
/* White */ /* White */
@ -441,7 +464,7 @@ static void set_simple_colour_map(t43_decode_state_t *s, int code)
/* Black */ /* Black */
s->colour_map_entries = 256; s->colour_map_entries = 256;
break; break;
case 2: case T43_IMAGE_TYPE_CMYK_BILEVEL:
/* Table 1/T.43 1 bit/colour image (using CMYK primaries) */ /* Table 1/T.43 1 bit/colour image (using CMYK primaries) */
memset(s->colour_map, 0, sizeof(s->colour_map)); memset(s->colour_map, 0, sizeof(s->colour_map));
/* White */ /* White */
@ -465,16 +488,26 @@ static void set_simple_colour_map(t43_decode_state_t *s, int code)
/* Black */ /* Black */
s->colour_map_entries = 256; s->colour_map_entries = 256;
break; break;
case 16: case T43_IMAGE_TYPE_8BIT_COLOUR_PALETTE:
/* Palettized colour image (using CIELAB 8 bits/component precision table) */ /* Palettized colour image (using CIELAB 8 bits/component precision table) */
for (i = 0; i < 3*256; i += 3)
{
s->colour_map[i + 0] = i;
s->colour_map[i + 1] = i;
s->colour_map[i + 2] = i;
}
s->colour_map_entries = 256;
break; break;
case 17: case T43_IMAGE_TYPE_12BIT_COLOUR_PALETTE:
/* Palettized colour image (using CIELAB 12 bits/component precision table) */ /* Palettized colour image (using CIELAB 12 bits/component precision table) */
break; break;
case 32: case T43_IMAGE_TYPE_GRAY:
/* Gray-scale image (using L*) */ /* Gray-scale image (using L*) */
for (i = 0; i < 256; i++)
s->colour_map[i] = i;
s->colour_map_entries = 256;
break; break;
case 48: case T43_IMAGE_TYPE_COLOUR:
/* Continuous-tone colour image (using CIELAB) */ /* Continuous-tone colour image (using CIELAB) */
break; break;
} }
@ -490,9 +523,6 @@ static int t43_analyse_header(t43_decode_state_t *s, const uint8_t data[], size_
uint8_t col[3]; uint8_t col[3];
int i; int i;
/* Set defaults */
set_lab_illuminant(&s->lab, 0.9638f, 1.0f, 0.8245f);
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, FALSE);
pos = 0; pos = 0;
if (pack_16(&data[pos]) != 0xFFA8) if (pack_16(&data[pos]) != 0xFFA8)
return 0; return 0;
@ -520,48 +550,68 @@ static int t43_analyse_header(t43_decode_state_t *s, const uint8_t data[], size_
{ {
case 0: case 0:
span_log(&s->logging, SPAN_LOG_FLOW, "Got G3FAX0\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Got G3FAX0\n");
if (seg >= 6 + 10) if (seg < 6 + 10)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX0 length - %d\n", seg);
}
else
{ {
val[0] = pack_16(&data[pos + 6 + 0]); val[0] = pack_16(&data[pos + 6 + 0]);
s->spatial_resolution = pack_16(&data[pos + 6 + 2]); s->spatial_resolution = pack_16(&data[pos + 6 + 2]);
val[2] = data[pos + 6 + 4]; val[2] = data[pos + 6 + 4];
val[3] = data[pos + 6 + 5]; s->image_type = data[pos + 6 + 5];
s->bit_planes[0] = data[pos + 6 + 6]; s->bit_planes[0] = data[pos + 6 + 6];
s->bit_planes[1] = data[pos + 6 + 7]; s->bit_planes[1] = data[pos + 6 + 7];
s->bit_planes[2] = data[pos + 6 + 8]; s->bit_planes[2] = data[pos + 6 + 8];
s->bit_planes[3] = data[pos + 6 + 9]; s->bit_planes[3] = data[pos + 6 + 9];
if (s->image_type == T43_IMAGE_TYPE_GRAY)
{
s->samples_per_pixel = 1;
}
else if (s->image_type == T43_IMAGE_TYPE_CMYK_BILEVEL)
{
s->samples_per_pixel = 4;
}
else
{
s->samples_per_pixel = 3;
}
span_log(&s->logging, span_log(&s->logging,
SPAN_LOG_FLOW, SPAN_LOG_FLOW,
"Version %d, resolution %.2fdpi, coding method %d, type %s (%d), bit planes %d,%d,%d,%d\n", "Version %d, resolution %ddpi, coding method %d, type %s (%d), bit planes %d,%d,%d,%d\n",
val[0], val[0],
s->spatial_resolution/100.0f, s->spatial_resolution,
val[2], val[2],
t43_image_type_to_str(val[3]), t43_image_type_to_str(s->image_type),
val[3], s->image_type,
s->bit_planes[0], s->bit_planes[0],
s->bit_planes[1], s->bit_planes[1],
s->bit_planes[2], s->bit_planes[2],
s->bit_planes[3]); s->bit_planes[3]);
set_simple_colour_map(s, val[3]); set_simple_colour_map(s, s->image_type);
}
else
{
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX0 length - %d\n", seg);
} }
break; break;
case 1: case 1:
span_log(&s->logging, SPAN_LOG_FLOW, "Set gamut\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Set gamut\n");
if (seg >= 6 + 12) if (seg < 6 + 12)
set_gamut_from_code(&s->logging, &s->lab, &data[pos + 6]); {
else
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX1 length - %d\n", seg); span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX1 length - %d\n", seg);
}
else
{
set_gamut_from_code(&s->logging, &s->lab, &data[pos + 6]);
}
break; break;
case 2: case 2:
span_log(&s->logging, SPAN_LOG_FLOW, "Set illuminant\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Set illuminant\n");
if (seg >= 6 + 4) if (seg < 6 + 4)
set_illuminant_from_code(&s->logging, &s->lab, &data[pos + 6]); {
else
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX2 length - %d\n", seg); span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX2 length - %d\n", seg);
}
else
{
s->illuminant_colour_temperature = set_illuminant_from_code(&s->logging, &s->lab, &data[pos + 6]);
}
break; break;
default: default:
span_log(&s->logging, SPAN_LOG_FLOW, "Got unexpected G3FAX%d length - %d\n", data[pos + 5], seg); span_log(&s->logging, SPAN_LOG_FLOW, "Got unexpected G3FAX%d length - %d\n", data[pos + 5], seg);
@ -588,7 +638,7 @@ static int t43_analyse_header(t43_decode_state_t *s, const uint8_t data[], size_
case 0: case 0:
/* 8 bit CIELAB */ /* 8 bit CIELAB */
s->colour_map_entries = pack_32(&data[pos + 8]); s->colour_map_entries = pack_32(&data[pos + 8]);
span_log(&s->logging, SPAN_LOG_FLOW, " Entries %6d\n", s->colour_map_entries); span_log(&s->logging, SPAN_LOG_FLOW, " Entries %6d (len %d)\n", s->colour_map_entries, seg);
if (seg >= 12 + s->colour_map_entries*3) if (seg >= 12 + s->colour_map_entries*3)
{ {
lab_to_srgb(&s->lab, s->colour_map, &data[pos + 12], s->colour_map_entries); lab_to_srgb(&s->lab, s->colour_map, &data[pos + 12], s->colour_map_entries);
@ -650,7 +700,7 @@ static int t85_row_write_handler(void *user_data, const uint8_t buf[], size_t le
if (s->buf == NULL) if (s->buf == NULL)
{ {
image_size = 3*s->t85.xd*s->t85.yd; image_size = s->samples_per_pixel*s->t85.xd*s->t85.yd;
if ((s->buf = malloc(image_size)) == NULL) if ((s->buf = malloc(image_size)) == NULL)
return -1; return -1;
memset(s->buf, 0, image_size); memset(s->buf, 0, image_size);
@ -659,13 +709,25 @@ static int t85_row_write_handler(void *user_data, const uint8_t buf[], size_t le
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
mask = 0x80; mask = 0x80;
for (j = 0; j < 24; j += 3) if (s->samples_per_pixel == 1)
{
for (j = 0; j < 8; j += s->samples_per_pixel)
{ {
if ((buf[i] & mask)) if ((buf[i] & mask))
s->buf[s->ptr + j] |= s->bit_plane_mask; s->buf[s->ptr + j] |= s->bit_plane_mask;
mask >>= 1; mask >>= 1;
} }
s->ptr += 3*8; }
else
{
for (j = 0; j < s->samples_per_pixel*8; j += s->samples_per_pixel)
{
if ((buf[i] & mask))
s->buf[s->ptr + j] |= s->bit_plane_mask;
mask >>= 1;
}
}
s->ptr += s->samples_per_pixel*8;
} }
s->row++; s->row++;
return 0; return 0;
@ -724,17 +786,23 @@ SPAN_DECLARE(int) t43_decode_put(t43_decode_state_t *s, const uint8_t data[], si
t85_decode_new_plane(&s->t85); t85_decode_new_plane(&s->t85);
} }
/* Apply the colour map, and produce the RGB data from the collected bit-planes */ /* Apply the colour map, and produce the RGB data from the collected bit-planes */
for (j = 0; j < total_len; j += 3) if (s->samples_per_pixel == 1)
{
for (j = 0; j < total_len; j += s->samples_per_pixel)
s->buf[j] = s->colour_map[s->buf[j]];
}
else
{
for (j = 0; j < total_len; j += s->samples_per_pixel)
{ {
i = s->buf[j]; i = s->buf[j];
s->buf[j] = s->colour_map[3*i]; s->buf[j] = s->colour_map[3*i];
s->buf[j + 1] = s->colour_map[3*i + 1]; s->buf[j + 1] = s->colour_map[3*i + 1];
s->buf[j + 2] = s->colour_map[3*i + 2]; s->buf[j + 2] = s->colour_map[3*i + 2];
} }
for (j = 0; j < s->t85.yd; j++)
{
s->row_write_handler(s->row_write_user_data, &s->buf[j*3*s->t85.xd], 3*s->t85.xd);
} }
for (j = 0; j < s->t85.yd; j++)
s->row_write_handler(s->row_write_user_data, &s->buf[j*s->samples_per_pixel*s->t85.xd], s->samples_per_pixel*s->t85.xd);
return result; return result;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -794,6 +862,17 @@ SPAN_DECLARE(logging_state_t *) t43_decode_get_logging_state(t43_decode_state_t
SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s) SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s)
{ {
/* ITULAB */
/* Illuminant D50 */
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, FALSE);
s->t85.min_bit_planes = 1;
s->t85.max_bit_planes = 8;
s->bit_plane_mask = 0x80;
s->current_bit_plane = -1;
s->image_type = T43_IMAGE_TYPE_8BIT_COLOUR_PALETTE;
return t85_decode_restart(&s->t85); return t85_decode_restart(&s->t85);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -816,10 +895,16 @@ SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s,
t85_decode_init(&s->t85, t85_row_write_handler, s); t85_decode_init(&s->t85, t85_row_write_handler, s);
/* ITULAB */
/* Illuminant D50 */
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, FALSE);
s->t85.min_bit_planes = 1; s->t85.min_bit_planes = 1;
s->t85.max_bit_planes = 8; s->t85.max_bit_planes = 8;
s->bit_plane_mask = 0x80; s->bit_plane_mask = 0x80;
s->current_bit_plane = -1; s->current_bit_plane = -1;
s->image_type = T43_IMAGE_TYPE_8BIT_COLOUR_PALETTE;
return s; return s;
} }

View File

@ -110,9 +110,9 @@ SPAN_DECLARE(const char *) t4_compression_to_str(int compression)
case T4_COMPRESSION_T88: case T4_COMPRESSION_T88:
return "T.88"; return "T.88";
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
return "T.81"; return "T.81+T.42";
case T4_COMPRESSION_SYCC_T81: case T4_COMPRESSION_SYCC_T81:
return "sYCC T.81"; return "T.81+sYCC";
case T4_COMPRESSION_T43: case T4_COMPRESSION_T43:
return "T.43"; return "T.43";
case T4_COMPRESSION_T45: case T4_COMPRESSION_T45:
@ -130,14 +130,20 @@ SPAN_DECLARE(const char *) t4_image_type_to_str(int type)
return "bi-level"; return "bi-level";
case T4_IMAGE_TYPE_COLOUR_BILEVEL: case T4_IMAGE_TYPE_COLOUR_BILEVEL:
return "bi-level colour"; return "bi-level colour";
case T4_IMAGE_TYPE_4COLOUR_BILEVEL:
return "CMYK bi-level colour";
case T4_IMAGE_TYPE_GRAY_8BIT: case T4_IMAGE_TYPE_GRAY_8BIT:
return "8-bit gray scale"; return "8-bit gray scale";
case T4_IMAGE_TYPE_GRAY_12BIT: case T4_IMAGE_TYPE_GRAY_12BIT:
return "12-bit gray scale"; return "12-bit gray scale";
case T4_IMAGE_TYPE_COLOUR_8BIT: case T4_IMAGE_TYPE_COLOUR_8BIT:
return "8-bit colour"; return "8-bit colour";
case T4_IMAGE_TYPE_4COLOUR_8BIT:
return "CMYK 8-bit colour";
case T4_IMAGE_TYPE_COLOUR_12BIT: case T4_IMAGE_TYPE_COLOUR_12BIT:
return "12-bit colour"; return "12-bit colour";
case T4_IMAGE_TYPE_4COLOUR_12BIT:
return "CMYK 12-bit colour";
} }
return "???"; return "???";
} }
@ -751,9 +757,9 @@ static void select_tiff_compression(t4_rx_state_t *s, int output_image_type)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding) SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
{ {
switch (encoding) switch (compression)
{ {
case T4_COMPRESSION_T4_1D: case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T4_2D:
@ -765,12 +771,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
break; break;
default: default:
t4_t6_decode_init(&s->decoder.t4_t6, encoding, s->metadata.image_width, s->row_handler, s->row_handler_user_data); t4_t6_decode_init(&s->decoder.t4_t6, compression, s->metadata.image_width, s->row_handler, s->row_handler_user_data);
break; break;
} }
s->metadata.compression = encoding; s->metadata.compression = compression;
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
return t4_t6_decode_set_encoding(&s->decoder.t4_t6, encoding); return t4_t6_decode_set_encoding(&s->decoder.t4_t6, compression);
case T4_COMPRESSION_T85: case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0: case T4_COMPRESSION_T85_L0:
switch (s->metadata.compression) switch (s->metadata.compression)
@ -787,7 +793,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
break; break;
} }
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
s->metadata.compression = encoding; s->metadata.compression = compression;
return 0; return 0;
#if defined(SPANDSP_SUPPORT_T88) #if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88: case T4_COMPRESSION_T88:
@ -799,7 +805,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
break; break;
} }
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
s->metadata.compression = encoding; s->metadata.compression = compression;
return 0; return 0;
#endif #endif
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
@ -817,7 +823,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
t42_decode_set_image_size_constraints(&s->decoder.t42, T4_WIDTH_1200_A3, 0); t42_decode_set_image_size_constraints(&s->decoder.t42, T4_WIDTH_1200_A3, 0);
break; break;
} }
s->metadata.compression = encoding; s->metadata.compression = compression;
select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT);
return 0; return 0;
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
@ -834,7 +840,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
t43_decode_set_image_size_constraints(&s->decoder.t43, T4_WIDTH_1200_A3, 0); t43_decode_set_image_size_constraints(&s->decoder.t43, T4_WIDTH_1200_A3, 0);
break; break;
} }
s->metadata.compression = encoding; s->metadata.compression = compression;
select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT);
return 0; return 0;
#endif #endif
@ -847,7 +853,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
default: default:
break; break;
} }
s->metadata.compression = encoding; s->metadata.compression = compression;
select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT);
return 0; return 0;
#endif #endif

View File

@ -57,8 +57,8 @@
#include "config.h" #include "config.h"
#endif #endif
#include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
@ -983,13 +983,15 @@ SPAN_DECLARE(int) t4_t6_encode_set_encoding(t4_t6_encode_state_t *s, int encodin
switch (encoding) switch (encoding)
{ {
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
s->min_bits_per_row = 0;
/* Fall through */
case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T4_1D: case T4_COMPRESSION_T4_1D:
s->encoding = encoding; s->encoding = encoding;
/* Set this to the default value for the lowest resolution in the T.4 spec. */ /* Set this to the default value for the lowest resolution in the T.4 spec. */
s->max_rows_to_next_1d_row = 2; s->max_rows_to_next_1d_row = 2;
s->rows_to_next_1d_row = s->max_rows_to_next_1d_row - 1; s->rows_to_next_1d_row = s->max_rows_to_next_1d_row - 1;
s->row_is_2d = FALSE; s->row_is_2d = (s->encoding == T4_COMPRESSION_T6);
return 0; return 0;
} }
return -1; return -1;
@ -998,7 +1000,16 @@ SPAN_DECLARE(int) t4_t6_encode_set_encoding(t4_t6_encode_state_t *s, int encodin
SPAN_DECLARE(void) t4_t6_encode_set_min_bits_per_row(t4_t6_encode_state_t *s, int bits) SPAN_DECLARE(void) t4_t6_encode_set_min_bits_per_row(t4_t6_encode_state_t *s, int bits)
{ {
switch (s->encoding)
{
case T4_COMPRESSION_T6:
s->min_bits_per_row = 0;
break;
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T4_1D:
s->min_bits_per_row = bits; s->min_bits_per_row = bits;
break;
}
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -1056,9 +1067,12 @@ SPAN_DECLARE(void) t4_t6_encode_set_max_2d_rows_per_1d_row(t4_t6_encode_state_t
} y_res_table[] = } y_res_table[] =
{ {
{T4_Y_RESOLUTION_STANDARD, 2}, {T4_Y_RESOLUTION_STANDARD, 2},
{T4_Y_RESOLUTION_100, 2},
{T4_Y_RESOLUTION_FINE, 4}, {T4_Y_RESOLUTION_FINE, 4},
{T4_Y_RESOLUTION_200, 4},
{T4_Y_RESOLUTION_300, 6}, {T4_Y_RESOLUTION_300, 6},
{T4_Y_RESOLUTION_SUPERFINE, 8}, {T4_Y_RESOLUTION_SUPERFINE, 8},
{T4_Y_RESOLUTION_400, 8},
{T4_Y_RESOLUTION_600, 12}, {T4_Y_RESOLUTION_600, 12},
{T4_Y_RESOLUTION_800, 16}, {T4_Y_RESOLUTION_800, 16},
{T4_Y_RESOLUTION_1200, 24}, {T4_Y_RESOLUTION_1200, 24},
@ -1094,7 +1108,7 @@ SPAN_DECLARE(logging_state_t *) t4_t6_encode_get_logging_state(t4_t6_encode_stat
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t4_t6_encode_restart(t4_t6_encode_state_t *s, int image_width) SPAN_DECLARE(int) t4_t6_encode_restart(t4_t6_encode_state_t *s, int image_width, int image_length)
{ {
/* Allow for pages being of different width. */ /* Allow for pages being of different width. */
t4_t6_encode_set_image_width(s, image_width); t4_t6_encode_set_image_width(s, image_width);
@ -1125,6 +1139,7 @@ SPAN_DECLARE(int) t4_t6_encode_restart(t4_t6_encode_state_t *s, int image_width)
SPAN_DECLARE(t4_t6_encode_state_t *) t4_t6_encode_init(t4_t6_encode_state_t *s, SPAN_DECLARE(t4_t6_encode_state_t *) t4_t6_encode_init(t4_t6_encode_state_t *s,
int encoding, int encoding,
int image_width, int image_width,
int image_length,
t4_row_read_handler_t handler, t4_row_read_handler_t handler,
void *user_data) void *user_data)
{ {
@ -1142,7 +1157,7 @@ SPAN_DECLARE(t4_t6_encode_state_t *) t4_t6_encode_init(t4_t6_encode_state_t *s,
s->row_read_user_data = user_data; s->row_read_user_data = user_data;
s->max_rows_to_next_1d_row = 2; s->max_rows_to_next_1d_row = 2;
t4_t6_encode_restart(s, image_width); t4_t6_encode_restart(s, image_width, image_length);
return s; return s;
} }

View File

@ -29,8 +29,8 @@
#include "config.h" #include "config.h"
#endif #endif
#include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
@ -91,6 +91,7 @@ typedef struct
uint8_t *buf; uint8_t *buf;
int ptr; int ptr;
int row; int row;
int size;
int bit_mask; int bit_mask;
} packer_t; } packer_t;
@ -100,7 +101,7 @@ typedef struct
int code; int code;
} res_table_t; } res_table_t;
static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length); static void t4_tx_set_image_length(t4_tx_state_t *s, uint32_t image_length);
static const res_table_t x_res_table[] = static const res_table_t x_res_table[] =
{ {
@ -1102,7 +1103,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_encoding(t4_tx_state_t *s, int encoding)
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
break; break;
default: default:
t4_t6_encode_init(&s->encoder.t4_t6, encoding, s->metadata.image_width, s->row_handler, s->row_handler_user_data); t4_t6_encode_init(&s->encoder.t4_t6, encoding, s->metadata.image_width, s->metadata.image_length, s->row_handler, s->row_handler_user_data);
t4_t6_encode_set_max_2d_rows_per_1d_row(&s->encoder.t4_t6, -s->metadata.y_resolution); t4_t6_encode_set_max_2d_rows_per_1d_row(&s->encoder.t4_t6, -s->metadata.y_resolution);
break; break;
} }
@ -1227,7 +1228,7 @@ SPAN_DECLARE(void) t4_tx_set_image_width(t4_tx_state_t *s, int image_width)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length) static void t4_tx_set_image_length(t4_tx_state_t *s, uint32_t image_length)
{ {
s->metadata.image_length = image_length; s->metadata.image_length = image_length;
switch (s->metadata.compression) switch (s->metadata.compression)
@ -1495,7 +1496,7 @@ SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s)
case T4_COMPRESSION_T4_1D: case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
t4_t6_encode_restart(&s->encoder.t4_t6, s->metadata.image_width); t4_t6_encode_restart(&s->encoder.t4_t6, s->metadata.image_width, s->metadata.image_length);
break; break;
case T4_COMPRESSION_T85: case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0: case T4_COMPRESSION_T85_L0:

View File

@ -845,6 +845,7 @@ int main(int argc, char *argv[])
| T4_SUPPORT_LENGTH_US_LETTER | T4_SUPPORT_LENGTH_US_LETTER
| T4_SUPPORT_LENGTH_US_LEGAL | T4_SUPPORT_LENGTH_US_LEGAL
| T4_SUPPORT_LENGTH_UNLIMITED); | T4_SUPPORT_LENGTH_UNLIMITED);
#if 0
t30_set_supported_bilevel_resolutions(t30_state[i], t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_R8_FINE | T4_SUPPORT_RESOLUTION_R8_FINE
@ -860,7 +861,36 @@ int main(int argc, char *argv[])
| T4_SUPPORT_RESOLUTION_600_600 | T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_600_1200 | T4_SUPPORT_RESOLUTION_600_1200
| T4_SUPPORT_RESOLUTION_1200_1200); | T4_SUPPORT_RESOLUTION_1200_1200);
#elif 0
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_R8_FINE
| T4_SUPPORT_RESOLUTION_R8_SUPERFINE
| T4_SUPPORT_RESOLUTION_R16_SUPERFINE);
#else
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_200_100
| T4_SUPPORT_RESOLUTION_200_200
| T4_SUPPORT_RESOLUTION_200_400
| T4_SUPPORT_RESOLUTION_300_300
| T4_SUPPORT_RESOLUTION_300_600
| T4_SUPPORT_RESOLUTION_400_400
| T4_SUPPORT_RESOLUTION_400_800
| T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_600_1200
| T4_SUPPORT_RESOLUTION_1200_1200);
#endif
#if 1
t30_set_supported_colour_resolutions(t30_state[i], 0); t30_set_supported_colour_resolutions(t30_state[i], 0);
#else
t30_set_supported_colour_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_100_100
| T4_SUPPORT_RESOLUTION_200_200
| T4_SUPPORT_RESOLUTION_300_300
| T4_SUPPORT_RESOLUTION_400_400
| T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_1200_1200);
#endif
t30_set_supported_output_compressions(t30_state[i], T4_SUPPORT_COMPRESSION_T4_2D); t30_set_supported_output_compressions(t30_state[i], T4_SUPPORT_COMPRESSION_T4_2D);
t30_set_ecm_capability(t30_state[i], use_ecm); t30_set_ecm_capability(t30_state[i], use_ecm);
t30_set_supported_compressions(t30_state[i], t30_set_supported_compressions(t30_state[i],

View File

@ -331,7 +331,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 ((send_state = t4_t6_encode_init(NULL, compression, 1728, row_read_handler, NULL)) == NULL) if ((send_state = t4_t6_encode_init(NULL, compression, 1728, -1, row_read_handler, NULL)) == NULL)
{ {
printf("Failed to init T.4/T.6 encoder\n"); printf("Failed to init T.4/T.6 encoder\n");
exit(2); exit(2);
@ -364,7 +364,7 @@ int main(int argc, char *argv[])
t4_t6_encode_set_encoding(send_state, compression); t4_t6_encode_set_encoding(send_state, compression);
t4_t6_decode_set_encoding(receive_state, compression); t4_t6_decode_set_encoding(receive_state, compression);
if (t4_t6_encode_restart(send_state, 1728)) if (t4_t6_encode_restart(send_state, 1728, -1))
break; break;
if (t4_t6_decode_restart(receive_state, 1728)) if (t4_t6_decode_restart(receive_state, 1728))
break; break;