More steps towards colour FAX

This commit is contained in:
Steve Underwood 2013-04-11 18:08:32 +08:00
parent fe4dff7c2d
commit 9eab201f93
9 changed files with 499 additions and 372 deletions

View File

@ -222,10 +222,12 @@ struct t30_state_s
int local_interrupt_pending; int local_interrupt_pending;
/*! \brief The common ground in compression schemes between the local and far ends. */ /*! \brief The common ground in compression schemes between the local and far ends. */
int mutual_compressions; int mutual_compressions;
/*! \brief The common group supported bi-level image resolutions. */ /*! \brief The common group of supported bi-level image resolutions. */
int mutual_bilevel_resolutions; int mutual_bilevel_resolutions;
/*! \brief The common group supported colour image resolutions. */ /*! \brief The common group of supported colour image resolutions. */
int mutual_colour_resolutions; int mutual_colour_resolutions;
/*! \brief The common group of supported image sizes. */
int mutual_image_sizes;
/*! \brief The image coding being used on the line. */ /*! \brief The image coding being used on the line. */
int line_encoding; int line_encoding;
/*! \brief The image coding being used for output files. */ /*! \brief The image coding being used for output files. */

View File

@ -80,9 +80,17 @@
/* Standard facsimile terminals conforming to ITU-T Rec. T.4 must have the following capability: /* Standard facsimile terminals conforming to ITU-T Rec. T.4 must have the following capability:
Paper length = 297 mm. */ Paper length = 297 mm. */
/* Bits 17, 18 - recording width */ #define T30_DIS_BIT_215MM_255MM_WIDTH_CAPABLE 17
#define T30_DCS_BIT_255MM_WIDTH 17
/* Bits 19, 20 - paper length */ #define T30_DIS_BIT_215MM_255MM_303MM_WIDTH_CAPABLE 18
#define T30_DCS_BIT_303MM_WIDTH 18
#define T30_DIS_BIT_A4_B4_LENGTH_CAPABLE 19
#define T30_DCS_BIT_B4_LENGTH 19
#define T30_DIS_BIT_UNLIMITED_LENGTH_CAPABLE 20
#define T30_DCS_BIT_UNLIMITED_LENGTH 20
/* Bits 21, 22, 23 - min scan line time */ /* Bits 21, 22, 23 - min scan line time */

View File

@ -82,6 +82,10 @@ typedef struct
int x_resolution; int x_resolution;
/*! \brief Row-to-row (Y) resolution in pixels per metre on the wire. */ /*! \brief Row-to-row (Y) resolution in pixels per metre on the wire. */
int y_resolution; int y_resolution;
/*! \brief Code for the combined X and Y resolution of the image in the file. */
int resolution_code;
/*! \brief Image type - bi-level, gray, colour, etc. */
int image_type;
} t4_tx_metadata_t; } t4_tx_metadata_t;
/*! /*!

View File

@ -98,11 +98,11 @@ enum
T30_SUPPORT_COMPRESSION_GRAYSCALE = 0x1000000, T30_SUPPORT_COMPRESSION_GRAYSCALE = 0x1000000,
/*! Colour support by multi-level codecs */ /*! Colour support by multi-level codecs */
T30_SUPPORT_COMPRESSION_COLOUR = 0x2000000, T30_SUPPORT_COMPRESSION_COLOUR = 0x2000000,
/*! 12 bit mode for gray scale and colour */ /*! 12 bit mode for gray-scale and colour */
T30_SUPPORT_COMPRESSION_12BIT = 0x4000000, T30_SUPPORT_COMPRESSION_12BIT = 0x4000000,
/*! Convert a colour image to a gray-scale one */ /*! Convert a colour image to a gray-scale one */
T30_SUPPORT_COMPRESSION_COLOUR_TO_GRAY = 0x8000000, T30_SUPPORT_COMPRESSION_COLOUR_TO_GRAY = 0x8000000,
/*! Dither a gray scale image down a simple bilevel image, with rescaling to fit a FAX page */ /*! Dither a gray-scale image down a simple bilevel image, with rescaling to fit a FAX page */
T30_SUPPORT_GRAY_TO_BILEVEL = 0x10000000, T30_SUPPORT_GRAY_TO_BILEVEL = 0x10000000,
/*! Dither a colour image down a simple bilevel image, with rescaling to fit a FAX page */ /*! Dither a colour image down a simple bilevel image, with rescaling to fit a FAX page */
T30_SUPPORT_COLOUR_TO_BILEVEL = 0x20000000, T30_SUPPORT_COLOUR_TO_BILEVEL = 0x20000000,
@ -141,7 +141,7 @@ typedef enum
T4_X_RESOLUTION_200 = 7874, T4_X_RESOLUTION_200 = 7874,
T4_X_RESOLUTION_R8 = 8031, T4_X_RESOLUTION_R8 = 8031,
T4_X_RESOLUTION_300 = 11811, T4_X_RESOLUTION_300 = 11811,
T4_X_RESOLUTION_400 = 15784, T4_X_RESOLUTION_400 = 15748,
T4_X_RESOLUTION_R16 = 16063, T4_X_RESOLUTION_R16 = 16063,
T4_X_RESOLUTION_600 = 23622, T4_X_RESOLUTION_600 = 23622,
T4_X_RESOLUTION_800 = 31496, T4_X_RESOLUTION_800 = 31496,
@ -176,27 +176,27 @@ enum
/*! Double FAX resolution 408dpi x 391dpi - bi-level only */ /*! Double FAX resolution 408dpi x 391dpi - bi-level only */
T4_RESOLUTION_R16_SUPERFINE = 4, T4_RESOLUTION_R16_SUPERFINE = 4,
/*! 100dpi x 100 dpi - gray-scale and colour only */ /*! 100dpi x 100dpi - gray-scale and colour only */
T4_RESOLUTION_100_100 = 5, T4_RESOLUTION_100_100 = 5,
/*! 200dpi x 100 dpi - bi-level only */ /*! 200dpi x 100dpi - bi-level only */
T4_RESOLUTION_200_100 = 6, T4_RESOLUTION_200_100 = 6,
/*! 200dpi x 200 dpi */ /*! 200dpi x 200dpi */
T4_RESOLUTION_200_200 = 7, T4_RESOLUTION_200_200 = 7,
/*! 200dpi x 400 dpi - bi-level only */ /*! 200dpi x 400dpi - bi-level only */
T4_RESOLUTION_200_400 = 8, T4_RESOLUTION_200_400 = 8,
/*! 300dpi x 300 dpi */ /*! 300dpi x 300dpi */
T4_RESOLUTION_300_300 = 9, T4_RESOLUTION_300_300 = 9,
/*! 300dpi x 600 dpi - bi-level only */ /*! 300dpi x 600dpi - bi-level only */
T4_RESOLUTION_300_600 = 10, T4_RESOLUTION_300_600 = 10,
/*! 400dpi x 400 dpi */ /*! 400dpi x 400dpi */
T4_RESOLUTION_400_400 = 11, T4_RESOLUTION_400_400 = 11,
/*! 400dpi x 800 dpi - bi-level only */ /*! 400dpi x 800dpi - bi-level only */
T4_RESOLUTION_400_800 = 12, T4_RESOLUTION_400_800 = 12,
/*! 600dpi x 600 dpi */ /*! 600dpi x 600dpi */
T4_RESOLUTION_600_600 = 13, T4_RESOLUTION_600_600 = 13,
/*! 600dpi x 1200 dpi - bi-level only */ /*! 600dpi x 1200dpi - bi-level only */
T4_RESOLUTION_600_1200 = 14, T4_RESOLUTION_600_1200 = 14,
/*! 1200dpi x 1200 dpi */ /*! 1200dpi x 1200dpi */
T4_RESOLUTION_1200_1200 = 15 T4_RESOLUTION_1200_1200 = 15
}; };
@ -211,27 +211,27 @@ enum
/*! Support double FAX resolution 408dpi x 391dpi - bi-level only */ /*! Support double FAX resolution 408dpi x 391dpi - bi-level only */
T4_SUPPORT_RESOLUTION_R16_SUPERFINE = 0x8, T4_SUPPORT_RESOLUTION_R16_SUPERFINE = 0x8,
/*! Support 100dpi x 100 dpi - gray scale and colour only */ /*! Support 100dpi x 100dpi - gray-scale and colour only */
T4_SUPPORT_RESOLUTION_100_100 = 0x10, T4_SUPPORT_RESOLUTION_100_100 = 0x10,
/*! Support 200dpi x 100 dpi - bi-level only */ /*! Support 200dpi x 100dpi - bi-level only */
T4_SUPPORT_RESOLUTION_200_100 = 0x20, T4_SUPPORT_RESOLUTION_200_100 = 0x20,
/*! Support 200dpi x 200 dpi */ /*! Support 200dpi x 200dpi */
T4_SUPPORT_RESOLUTION_200_200 = 0x40, T4_SUPPORT_RESOLUTION_200_200 = 0x40,
/*! Support 200dpi x 400 dpi - bi-level only */ /*! Support 200dpi x 400dpi - bi-level only */
T4_SUPPORT_RESOLUTION_200_400 = 0x80, T4_SUPPORT_RESOLUTION_200_400 = 0x80,
/*! Support 300dpi x 300 dpi */ /*! Support 300dpi x 300dpi */
T4_SUPPORT_RESOLUTION_300_300 = 0x100, T4_SUPPORT_RESOLUTION_300_300 = 0x100,
/*! Support 300dpi x 600 dpi - bi-level only */ /*! Support 300dpi x 600dpi - bi-level only */
T4_SUPPORT_RESOLUTION_300_600 = 0x200, T4_SUPPORT_RESOLUTION_300_600 = 0x200,
/*! Support 400dpi x 400 dpi */ /*! Support 400dpi x 400dpi */
T4_SUPPORT_RESOLUTION_400_400 = 0x400, T4_SUPPORT_RESOLUTION_400_400 = 0x400,
/*! Support 400dpi x 800 dpi - bi-level only */ /*! Support 400dpi x 800dpi - bi-level only */
T4_SUPPORT_RESOLUTION_400_800 = 0x800, T4_SUPPORT_RESOLUTION_400_800 = 0x800,
/*! Support 600dpi x 600 dpi */ /*! Support 600dpi x 600dpi */
T4_SUPPORT_RESOLUTION_600_600 = 0x1000, T4_SUPPORT_RESOLUTION_600_600 = 0x1000,
/*! Support 600dpi x 1200 dpi - bi-level only */ /*! Support 600dpi x 1200dpi - bi-level only */
T4_SUPPORT_RESOLUTION_600_1200 = 0x2000, T4_SUPPORT_RESOLUTION_600_1200 = 0x2000,
/*! Support 1200dpi x 1200 dpi */ /*! Support 1200dpi x 1200dpi */
T4_SUPPORT_RESOLUTION_1200_1200 = 0x4000 T4_SUPPORT_RESOLUTION_1200_1200 = 0x4000
}; };
@ -542,10 +542,16 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding);
/*! Get the short text name of an image format. /*! Get the short text name of an image format.
\brief Get the short text name of an image format. \brief Get the short text name of an image format.
\param encoding The image format. \param type The image format.
\return A pointer to the string. */ \return A pointer to the string. */
SPAN_DECLARE(const char *) t4_image_type_to_str(int type); SPAN_DECLARE(const char *) t4_image_type_to_str(int type);
/*! Get the short text name of an image resolution.
\brief Get the short text name of an image resolution.
\param resolution_code The image resolution code.
\return A pointer to the string. */
SPAN_DECLARE(const char *) t4_image_resolution_to_str(int resolution_code);
/*! Get the logging context associated with a T.4 receive context. /*! Get the logging context associated with a T.4 receive context.
\brief Get the logging context associated with a T.4 receive context. \brief Get the logging context associated with a T.4 receive context.
\param s The T.4 receive context. \param s The T.4 receive context.

View File

@ -341,11 +341,21 @@ SPAN_DECLARE(int) t4_tx_get_y_resolution(t4_tx_state_t *s);
\return The resolution, in pixels per metre. */ \return The resolution, in pixels per metre. */
SPAN_DECLARE(int) t4_tx_get_x_resolution(t4_tx_state_t *s); SPAN_DECLARE(int) t4_tx_get_x_resolution(t4_tx_state_t *s);
/*! \brief Get the X and Y resolution code of the current page.
\param s The T.4 context.
\return The resolution code,. */
SPAN_DECLARE(int) t4_tx_get_resolution(t4_tx_state_t *s);
/*! \brief Get the width of the current page, in pixel columns. /*! \brief Get the width of the current page, in pixel columns.
\param s The T.4 context. \param s The T.4 context.
\return The number of columns. */ \return The number of columns. */
SPAN_DECLARE(int) t4_tx_get_image_width(t4_tx_state_t *s); SPAN_DECLARE(int) t4_tx_get_image_width(t4_tx_state_t *s);
/*! \brief Get the type of the current page, in pixel columns.
\param s The T.4 context.
\return The type. */
SPAN_DECLARE(int) t4_tx_get_image_type(t4_tx_state_t *s);
/*! \brief Get the number of pages in the file. /*! \brief Get the number of pages in the file.
\param s The T.4 context. \param s The T.4 context.
\return The number of pages, or -1 if there is an error. */ \return The number of pages, or -1 if there is an error. */

View File

@ -1144,6 +1144,29 @@ static int set_dis_or_dtc(t30_state_t *s)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static int prune_dis_dtc(t30_state_t *s)
{
int i;
/* Find the last octet that is really needed, set the extension bits, and trim the message length */
for (i = 18; i >= 6; i--)
{
/* Strip the top bit */
s->local_dis_dtc_frame[i] &= (DISBIT1 | DISBIT2 | DISBIT3 | DISBIT4 | DISBIT5 | DISBIT6 | DISBIT7);
/* Check if there is some real message content here */
if (s->local_dis_dtc_frame[i])
break;
}
s->local_dis_dtc_len = i + 1;
/* Fill in any required extension bits */
s->local_dis_dtc_frame[i] &= ~DISBIT8;
for (i--; i > 4; i--)
s->local_dis_dtc_frame[i] |= DISBIT8;
t30_decode_dis_dtc_dcs(s, s->local_dis_dtc_frame, s->local_dis_dtc_len);
return s->local_dis_dtc_len;
}
/*- End of function --------------------------------------------------------*/
int t30_build_dis_or_dtc(t30_state_t *s) int t30_build_dis_or_dtc(t30_state_t *s)
{ {
int i; int i;
@ -1181,15 +1204,19 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* 215mm wide is always supported */ /* 215mm wide is always supported */
if ((s->supported_image_sizes & T4_SUPPORT_WIDTH_303MM)) if ((s->supported_image_sizes & T4_SUPPORT_WIDTH_303MM))
set_ctrl_bit(s->local_dis_dtc_frame, 18); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_215MM_255MM_303MM_WIDTH_CAPABLE);
else if ((s->supported_image_sizes & T4_SUPPORT_WIDTH_255MM)) else if ((s->supported_image_sizes & T4_SUPPORT_WIDTH_255MM))
set_ctrl_bit(s->local_dis_dtc_frame, 17); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_215MM_255MM_WIDTH_CAPABLE);
/* A4 is always supported. */ /* A4 is always supported. */
if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED)) if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
set_ctrl_bit(s->local_dis_dtc_frame, 20); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_UNLIMITED_LENGTH_CAPABLE);
else if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_B4)) else if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_B4))
set_ctrl_bit(s->local_dis_dtc_frame, 19); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_A4_B4_LENGTH_CAPABLE);
if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_US_LETTER))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LETTER_CAPABLE);
if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_US_LEGAL))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LEGAL_CAPABLE);
/* No scan-line padding required, but some may be specified by the application. */ /* No scan-line padding required, but some may be specified by the application. */
set_ctrl_bits(s->local_dis_dtc_frame, s->local_min_scan_time_code, 21); set_ctrl_bits(s->local_dis_dtc_frame, s->local_min_scan_time_code, 21);
@ -1240,7 +1267,7 @@ int t30_build_dis_or_dtc(t30_state_t *s)
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_12BIT)) if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_12BIT))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE); set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE);
//if ((s->supported_compressions & 30_SUPPORT_COMPRESSION_NO_SUBSAMPLING)) //if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_NO_SUBSAMPLING))
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING); // set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
/* No custom illuminant */ /* No custom illuminant */
@ -1275,10 +1302,6 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* No mode 26 (T.505) */ /* No mode 26 (T.505) */
/* No digital network capability */ /* No digital network capability */
/* No duplex operation */ /* No duplex operation */
if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_US_LETTER))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LETTER_CAPABLE);
if ((s->supported_image_sizes & T4_SUPPORT_LENGTH_US_LEGAL))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LEGAL_CAPABLE);
/* No HKM key management */ /* No HKM key management */
/* No RSA key management */ /* No RSA key management */
/* No override */ /* No override */
@ -1365,34 +1388,20 @@ int t30_build_dis_or_dtc(t30_state_t *s)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static int prune_dis_dtc(t30_state_t *s)
{
int i;
/* Find the last octet that is really needed, set the extension bits, and trim the message length */
for (i = 18; i >= 6; i--)
{
/* Strip the top bit */
s->local_dis_dtc_frame[i] &= (DISBIT1 | DISBIT2 | DISBIT3 | DISBIT4 | DISBIT5 | DISBIT6 | DISBIT7);
/* Check if there is some real message content here */
if (s->local_dis_dtc_frame[i])
break;
}
s->local_dis_dtc_len = i + 1;
/* Fill in any required extension bits */
s->local_dis_dtc_frame[i] &= ~DISBIT8;
for (i--; i > 4; i--)
s->local_dis_dtc_frame[i] |= DISBIT8;
t30_decode_dis_dtc_dcs(s, s->local_dis_dtc_frame, s->local_dis_dtc_len);
return s->local_dis_dtc_len;
}
/*- End of function --------------------------------------------------------*/
static int build_dcs(t30_state_t *s) static int build_dcs(t30_state_t *s)
{ {
int i; int i;
int bad; int bad;
int row_squashing_ratio; int row_squashing_ratio;
int use_bilevel;
//int image_type;
/* Reacquire page information, in case the image was resized, flattened, etc. */
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
//s->current_page_resolution = t4_tx_get_resolution(&s->t4.tx);
s->image_width = t4_tx_get_image_width(&s->t4.tx);
//image_type = t4_tx_get_image_type(&s->t4.tx);
/* Make a DCS frame based on local issues and the latest received DIS/DTC frame. Negotiate /* Make a DCS frame based on local issues and the latest received DIS/DTC frame. Negotiate
the result based on what both parties can do. */ the result based on what both parties can do. */
@ -1414,17 +1423,35 @@ static int build_dcs(t30_state_t *s)
/* Set to required modem rate */ /* Set to required modem rate */
s->dcs_frame[4] |= fallback_sequence[s->current_fallback].dcs_code; s->dcs_frame[4] |= fallback_sequence[s->current_fallback].dcs_code;
/* We have a file to send, so tell the far end to go into receive mode. */
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT);
/* Select the compression to use. */ /* Select the compression to use. */
use_bilevel = TRUE;
switch (s->line_encoding) switch (s->line_encoding)
{ {
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T81_MODE);
//if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
// 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)
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
//if (???????? & T4_COMPRESSION_?????))
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
use_bilevel = FALSE;
break; break;
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43: case T4_COMPRESSION_T43:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE);
//if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
// 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)
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
//if (???????? & T4_COMPRESSION_?????))
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
use_bilevel = FALSE;
break; break;
#endif #endif
case T4_COMPRESSION_T85_L0: case T4_COMPRESSION_T85_L0:
@ -1450,154 +1477,166 @@ static int build_dcs(t30_state_t *s)
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
break; break;
} }
/* We have a file to send, so tell the far end to go into receive mode. */
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT);
/* Set the Y resolution bits */ /* Set the Y resolution bits */
bad = T30_ERR_NORESSUPPORT; bad = T30_ERR_NORESSUPPORT;
row_squashing_ratio = 1; row_squashing_ratio = 1;
switch (s->y_resolution) if (use_bilevel)
{ {
case T4_Y_RESOLUTION_1200: switch (s->y_resolution)
switch (s->x_resolution)
{ {
case T4_X_RESOLUTION_1200: case T4_Y_RESOLUTION_1200:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_1200_1200)) switch (s->x_resolution)
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200); case T4_X_RESOLUTION_1200:
bad = T30_ERR_OK; if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_1200_1200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
case T4_X_RESOLUTION_600:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_1200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
} }
break; break;
case T4_X_RESOLUTION_600: case T4_Y_RESOLUTION_800:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_1200)) switch (s->x_resolution)
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200); case T4_X_RESOLUTION_R16:
bad = T30_ERR_OK; if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_800))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
} }
break; break;
} case T4_Y_RESOLUTION_600:
break; switch (s->x_resolution)
case T4_Y_RESOLUTION_800:
switch (s->x_resolution)
{
case T4_X_RESOLUTION_R16:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_800))
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800); case T4_X_RESOLUTION_600:
bad = T30_ERR_OK; if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_600))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
case T4_X_RESOLUTION_300:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_600))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
} }
break; break;
} case T4_Y_RESOLUTION_300:
break; switch (s->x_resolution)
case T4_Y_RESOLUTION_600:
switch (s->x_resolution)
{
case T4_X_RESOLUTION_600:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_600))
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600); case T4_X_RESOLUTION_300:
bad = T30_ERR_OK; if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_300))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
} }
break; break;
case T4_X_RESOLUTION_300: case T4_Y_RESOLUTION_SUPERFINE:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_600)) case T4_Y_RESOLUTION_400:
if (s->x_resolution == T4_X_RESOLUTION_400 && s->y_resolution == T4_Y_RESOLUTION_400)
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600); if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_400))
bad = T30_ERR_OK; {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
break;
}
} }
break; else if (s->x_resolution == T4_X_RESOLUTION_R16 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
}
break;
case T4_Y_RESOLUTION_300:
switch (s->x_resolution)
{
case T4_X_RESOLUTION_300:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_300))
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300); if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R16_SUPERFINE))
bad = T30_ERR_OK; {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
bad = T30_ERR_OK;
break;
}
} }
break; else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_400)
}
break;
case T4_Y_RESOLUTION_SUPERFINE:
case T4_Y_RESOLUTION_400:
if (s->x_resolution == T4_X_RESOLUTION_400 && s->y_resolution == T4_Y_RESOLUTION_400)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_400))
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400); if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_400))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
break;
}
}
else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R8_SUPERFINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
bad = T30_ERR_OK;
break;
}
}
row_squashing_ratio <<= 1;
/* Fall through */
case T4_Y_RESOLUTION_FINE:
case T4_Y_RESOLUTION_200:
if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_200)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
break;
}
}
else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_FINE)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R8_FINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
bad = T30_ERR_OK;
break;
}
}
row_squashing_ratio <<= 1;
/* Fall through */
default:
case T4_Y_RESOLUTION_STANDARD:
case T4_Y_RESOLUTION_100:
if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_STANDARD)
{
/* No bits to set for this */
bad = T30_ERR_OK; bad = T30_ERR_OK;
break; break;
} }
} else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_100)
else if (s->x_resolution == T4_X_RESOLUTION_R16 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R16_SUPERFINE))
{ {
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK; bad = T30_ERR_OK;
break; break;
} }
}
else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_400)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_400))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
bad = T30_ERR_OK;
break;
}
}
else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R8_SUPERFINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
bad = T30_ERR_OK;
break;
}
}
row_squashing_ratio <<= 1;
/* Fall through */
case T4_Y_RESOLUTION_FINE:
case T4_Y_RESOLUTION_200:
if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_200)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
bad = T30_ERR_OK;
break;
}
}
else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_FINE)
{
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R8_FINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
bad = T30_ERR_OK;
break;
}
}
row_squashing_ratio <<= 1;
/* Fall through */
default:
case T4_Y_RESOLUTION_STANDARD:
case T4_Y_RESOLUTION_100:
if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_STANDARD)
{
/* No bits to set for this */
bad = T30_ERR_OK;
break; break;
} }
else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_100)
{
/* No bits to set for this */
bad = T30_ERR_OK;
break;
}
break;
} }
t4_tx_set_row_squashing_ratio(&s->t4.tx, row_squashing_ratio); t4_tx_set_row_squashing_ratio(&s->t4.tx, row_squashing_ratio);
if (bad != T30_ERR_OK) if (bad != T30_ERR_OK)
{ {
@ -1634,12 +1673,10 @@ static int build_dcs(t30_state_t *s)
|| ||
((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200))) ((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{ {
if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 1) if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_255MM))
&&
(s->supported_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\n");
set_ctrl_bit(s->dcs_frame, 17); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
} }
else else
{ {
@ -1657,12 +1694,10 @@ static int build_dcs(t30_state_t *s)
|| ||
((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200))) ((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{ {
if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 2) if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_303MM))
&&
(s->supported_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\n");
set_ctrl_bit(s->dcs_frame, 18); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
} }
else else
{ {
@ -1691,10 +1726,10 @@ static int build_dcs(t30_state_t *s)
/* Deal with the image length */ /* Deal with 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 (test_ctrl_bit(s->far_dis_dtc_frame, 20)) if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
set_ctrl_bit(s->dcs_frame, 20); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_UNLIMITED_LENGTH);
else if (test_ctrl_bit(s->far_dis_dtc_frame, 19)) else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_B4))
set_ctrl_bit(s->dcs_frame, 19); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_B4_LENGTH);
if (s->error_correcting_mode) if (s->error_correcting_mode)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_ECM_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_ECM_MODE);
@ -2167,9 +2202,11 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
memcpy(s->far_dis_dtc_frame, msg, s->far_dis_dtc_len); memcpy(s->far_dis_dtc_frame, msg, s->far_dis_dtc_len);
if (s->far_dis_dtc_len < T30_MAX_DIS_DTC_DCS_LEN) if (s->far_dis_dtc_len < T30_MAX_DIS_DTC_DCS_LEN)
memset(s->far_dis_dtc_frame + s->far_dis_dtc_len, 0, T30_MAX_DIS_DTC_DCS_LEN - s->far_dis_dtc_len); memset(s->far_dis_dtc_frame + s->far_dis_dtc_len, 0, T30_MAX_DIS_DTC_DCS_LEN - s->far_dis_dtc_len);
s->error_correcting_mode = (s->ecm_allowed && (s->far_dis_dtc_frame[6] & DISBIT3) != 0);
s->error_correcting_mode = (s->ecm_allowed && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_ECM_CAPABLE));
/* 256 octets per ECM frame */ /* 256 octets per ECM frame */
s->octets_per_ecm_frame = 256; s->octets_per_ecm_frame = 256;
/* Now we know if we are going to use ECM, select the compressions which we can use. */ /* Now we know if we are going to use ECM, select the compressions which we can use. */
s->mutual_compressions = s->supported_compressions; s->mutual_compressions = s->supported_compressions;
if (!s->error_correcting_mode) if (!s->error_correcting_mode)
@ -2283,6 +2320,24 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_100_100_CAPABLE)) if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_100_100_CAPABLE))
s->mutual_colour_resolutions &= ~T4_SUPPORT_RESOLUTION_100_100; s->mutual_colour_resolutions &= ~T4_SUPPORT_RESOLUTION_100_100;
s->mutual_image_sizes = s->supported_image_sizes;
/* 215mm wide is always supported */
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_215MM_255MM_303MM_WIDTH_CAPABLE))
{
s->mutual_image_sizes &= ~T4_SUPPORT_WIDTH_303MM;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_215MM_255MM_WIDTH_CAPABLE))
s->mutual_image_sizes &= ~T4_SUPPORT_WIDTH_255MM;
}
/* A4 is always supported. */
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_UNLIMITED_LENGTH_CAPABLE))
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_UNLIMITED;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_A4_B4_LENGTH_CAPABLE))
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_B4;
if (!test_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LETTER_CAPABLE))
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LETTER;
if (!test_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LEGAL_CAPABLE))
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LEGAL;
switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3)) switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
{ {
case (DISBIT6 | DISBIT4 | DISBIT3): case (DISBIT6 | DISBIT4 | DISBIT3):
@ -2443,7 +2498,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
s->x_resolution = -1; s->x_resolution = -1;
s->y_resolution = -1; s->y_resolution = -1;
//s->current_page_resolution = 0; s->current_page_resolution = 0;
x = -1; x = -1;
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_T43_MODE)) if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_T43_MODE))
{ {
@ -2471,7 +2526,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_1200; s->x_resolution = T4_X_RESOLUTION_1200;
s->y_resolution = T4_Y_RESOLUTION_1200; s->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_1200_1200; s->current_page_resolution = T4_RESOLUTION_1200_1200;
x = 5; x = 5;
} }
} }
@ -2481,7 +2536,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_600; s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_600; s->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_600_600; s->current_page_resolution = T4_RESOLUTION_600_600;
x = 4; x = 4;
} }
} }
@ -2491,7 +2546,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_400; s->x_resolution = T4_X_RESOLUTION_400;
s->y_resolution = T4_Y_RESOLUTION_400; s->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_400_400; s->current_page_resolution = T4_RESOLUTION_400_400;
x = 3; x = 3;
} }
} }
@ -2501,7 +2556,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_300; s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_300; s->y_resolution = T4_Y_RESOLUTION_300;
//s->current_page_resolution = T4_RESOLUTION_300_300; s->current_page_resolution = T4_RESOLUTION_300_300;
x = 2; x = 2;
} }
} }
@ -2511,7 +2566,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_200; s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_200; s->y_resolution = T4_Y_RESOLUTION_200;
//s->current_page_resolution = T4_RESOLUTION_200_200; s->current_page_resolution = T4_RESOLUTION_200_200;
x = 1; x = 1;
} }
} }
@ -2521,7 +2576,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_100; s->x_resolution = T4_X_RESOLUTION_100;
s->y_resolution = T4_Y_RESOLUTION_100; s->y_resolution = T4_Y_RESOLUTION_100;
//s->current_page_resolution = T4_RESOLUTION_100_100; s->current_page_resolution = T4_RESOLUTION_100_100;
x = 0; x = 0;
} }
} }
@ -2535,7 +2590,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_1200; s->x_resolution = T4_X_RESOLUTION_1200;
s->y_resolution = T4_Y_RESOLUTION_1200; s->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_1200_1200; s->current_page_resolution = T4_RESOLUTION_1200_1200;
x = 5; x = 5;
} }
} }
@ -2545,7 +2600,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_600; s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_1200; s->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_600_1200; s->current_page_resolution = T4_RESOLUTION_600_1200;
x = 4; x = 4;
} }
} }
@ -2555,7 +2610,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_600; s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_600; s->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_600_600; s->current_page_resolution = T4_RESOLUTION_600_600;
x = 4; x = 4;
} }
} }
@ -2565,7 +2620,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_400; s->x_resolution = T4_X_RESOLUTION_400;
s->y_resolution = T4_Y_RESOLUTION_800; s->y_resolution = T4_Y_RESOLUTION_800;
//s->current_page_resolution = T4_RESOLUTION_400_800; s->current_page_resolution = T4_RESOLUTION_400_800;
x = 3; x = 3;
} }
} }
@ -2577,7 +2632,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_400; s->x_resolution = T4_X_RESOLUTION_400;
s->y_resolution = T4_Y_RESOLUTION_400; s->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_400_400; s->current_page_resolution = T4_RESOLUTION_400_400;
x = 3; x = 3;
} }
} }
@ -2587,7 +2642,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_R16; s->x_resolution = T4_X_RESOLUTION_R16;
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
//s->current_page_resolution = T4_RESOLUTION_R16_SUPERFINE; s->current_page_resolution = T4_RESOLUTION_R16_SUPERFINE;
x = 3; x = 3;
} }
} }
@ -2598,7 +2653,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_300; s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_600; s->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_300_600; s->current_page_resolution = T4_RESOLUTION_300_600;
x = 2; x = 2;
} }
} }
@ -2608,7 +2663,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_300; s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_300; s->y_resolution = T4_Y_RESOLUTION_300;
//s->current_page_resolution = T4_RESOLUTION_300_300; s->current_page_resolution = T4_RESOLUTION_300_300;
x = 2; x = 2;
} }
} }
@ -2620,7 +2675,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_200; s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_400; s->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_200_400; s->current_page_resolution = T4_RESOLUTION_200_400;
x = 1; x = 1;
} }
} }
@ -2630,7 +2685,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_R8; s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
//s->current_page_resolution = T4_RESOLUTION_R8_SUPERFINE; s->current_page_resolution = T4_RESOLUTION_R8_SUPERFINE;
x = 1; x = 1;
} }
} }
@ -2643,7 +2698,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_200; s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_200; s->y_resolution = T4_Y_RESOLUTION_200;
//s->current_page_resolution = T4_RESOLUTION_200_200; s->current_page_resolution = T4_RESOLUTION_200_200;
x = 1; x = 1;
} }
} }
@ -2653,7 +2708,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_R8; s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_FINE; s->y_resolution = T4_Y_RESOLUTION_FINE;
//s->current_page_resolution = T4_RESOLUTION_R8_FINE; s->current_page_resolution = T4_RESOLUTION_R8_FINE;
x = 1; x = 1;
} }
} }
@ -2664,14 +2719,14 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{ {
s->x_resolution = T4_X_RESOLUTION_200; s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_100; s->y_resolution = T4_Y_RESOLUTION_100;
//s->current_page_resolution = T4_RESOLUTION_200_100; s->current_page_resolution = T4_RESOLUTION_200_100;
x = 1; x = 1;
} }
else else
{ {
s->x_resolution = T4_X_RESOLUTION_R8; s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_STANDARD; s->y_resolution = T4_Y_RESOLUTION_STANDARD;
//s->current_page_resolution = T4_RESOLUTION_R8_STANDARD; s->current_page_resolution = T4_RESOLUTION_R8_STANDARD;
x = 1; x = 1;
} }
} }

View File

@ -754,7 +754,10 @@ SPAN_DECLARE(int) t30_set_supported_colour_resolutions(t30_state_t *s, int suppo
SPAN_DECLARE(int) t30_set_supported_image_sizes(t30_state_t *s, int supported_image_sizes) SPAN_DECLARE(int) t30_set_supported_image_sizes(t30_state_t *s, int supported_image_sizes)
{ {
s->supported_image_sizes = supported_image_sizes; /* Force the sizes which are always available */
s->supported_image_sizes = supported_image_sizes
| T4_SUPPORT_WIDTH_215MM
| T4_SUPPORT_LENGTH_A4;
t30_build_dis_or_dtc(s); t30_build_dis_or_dtc(s);
return 0; return 0;
} }

View File

@ -141,6 +141,45 @@ SPAN_DECLARE(const char *) t4_image_type_to_str(int type)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(const char *) t4_image_resolution_to_str(int resolution_code)
{
switch (resolution_code)
{
case T4_RESOLUTION_R8_STANDARD:
return "204dpi x 98dpi";
case T4_RESOLUTION_R8_FINE:
return "204dpi x 196dpi";
case T4_RESOLUTION_R8_SUPERFINE:
return "204dpi x 391dpi";
case T4_RESOLUTION_R16_SUPERFINE:
return "408dpi x 391dpi";
case T4_RESOLUTION_100_100:
return "100dpi x 100dpi";
case T4_RESOLUTION_200_100:
return "200dpi x 100dpi";
case T4_RESOLUTION_200_200:
return "200dpi x 200dpi";
case T4_RESOLUTION_200_400:
return "200dpi x 400dpi";
case T4_RESOLUTION_300_300:
return "300dpi x 300dpi";
case T4_RESOLUTION_300_600:
return "300dpi x 600dpi";
case T4_RESOLUTION_400_400:
return "400dpi x 400dpi";
case T4_RESOLUTION_400_800:
return "400dpi x 800dpi";
case T4_RESOLUTION_600_600:
return "600dpi x 600dpi";
case T4_RESOLUTION_600_1200:
return "600dpi x 1200dpi";
case T4_RESOLUTION_1200_1200:
return "1200dpi x 1200dpi";
}
return "???";
}
/*- End of function --------------------------------------------------------*/
static int set_tiff_directory_info(t4_rx_state_t *s) static int set_tiff_directory_info(t4_rx_state_t *s)
{ {
time_t now; time_t now;
@ -175,6 +214,10 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
output_compression = COMPRESSION_CCITT_T6; output_compression = COMPRESSION_CCITT_T6;
break; break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
output_compression = COMPRESSION_T85;
break;
#if defined(SPANDSP_SUPPORT_T42) #if defined(SPANDSP_SUPPORT_T42)
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
output_compression = COMPRESSION_JPEG; output_compression = COMPRESSION_JPEG;
@ -191,10 +234,6 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
photometric = PHOTOMETRIC_ITULAB; photometric = PHOTOMETRIC_ITULAB;
break; break;
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
output_compression = COMPRESSION_T85;
break;
} }
TIFFSetField(t->tiff_file, TIFFTAG_COMPRESSION, output_compression); TIFFSetField(t->tiff_file, TIFFTAG_COMPRESSION, output_compression);
@ -208,6 +247,9 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
TIFFSetField(t->tiff_file, TIFFTAG_T6OPTIONS, 0); TIFFSetField(t->tiff_file, TIFFTAG_T6OPTIONS, 0);
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break; break;
case COMPRESSION_T85:
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break;
case COMPRESSION_JPEG: case COMPRESSION_JPEG:
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break; break;
@ -216,9 +258,6 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break; break;
#endif #endif
case COMPRESSION_T85:
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break;
} }
TIFFSetField(t->tiff_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(t->tiff_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, bits_per_sample); TIFFSetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
@ -304,6 +343,10 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
s->image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6); s->image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
break; break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
s->image_length = t85_decode_get_image_length(&s->decoder.t85);
break;
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
s->image_length = t42_decode_get_image_length(&s->decoder.t42); s->image_length = t42_decode_get_image_length(&s->decoder.t42);
break; break;
@ -312,10 +355,6 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
s->image_length = t43_decode_get_image_length(&s->decoder.t43); s->image_length = t43_decode_get_image_length(&s->decoder.t43);
break; break;
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
s->image_length = t85_decode_get_image_length(&s->decoder.t85);
break;
} }
TIFFSetField(t->tiff_file, TIFFTAG_IMAGELENGTH, s->image_length); TIFFSetField(t->tiff_file, TIFFTAG_IMAGELENGTH, s->image_length);
TIFFSetField(t->tiff_file, TIFFTAG_ROWSPERSTRIP, s->image_length); TIFFSetField(t->tiff_file, TIFFTAG_ROWSPERSTRIP, s->image_length);
@ -384,6 +423,7 @@ static int write_tiff_image(t4_rx_state_t *s)
{ {
case T4_COMPRESSION_T85: case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0: case T4_COMPRESSION_T85_L0:
/* We need to perform this compression here, as libtiff does not understand it. */
span_log(&s->logging, SPAN_LOG_WARNING, "%s: TODO need T.85 compression.\n", t->file); span_log(&s->logging, SPAN_LOG_WARNING, "%s: TODO need T.85 compression.\n", t->file);
buf_len = 0; buf_len = 0;
buf = NULL; buf = NULL;
@ -417,6 +457,7 @@ static int write_tiff_image(t4_rx_state_t *s)
break; break;
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43: case T4_COMPRESSION_T43:
/* We need to perform this compression here, as libtiff does not understand it. */
span_log(&s->logging, SPAN_LOG_WARNING, "%s: TODO need T.43 compression.\n", t->file); span_log(&s->logging, SPAN_LOG_WARNING, "%s: TODO need T.43 compression.\n", t->file);
buf_len = 0; buf_len = 0;
buf = NULL; buf = NULL;
@ -553,15 +594,15 @@ SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len)
case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
return t4_t6_decode_put(&s->decoder.t4_t6, buf, len); return t4_t6_decode_put(&s->decoder.t4_t6, buf, len);
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_put(&s->decoder.t85, buf, len);
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
return t42_decode_put(&s->decoder.t42, buf, len); return t42_decode_put(&s->decoder.t42, buf, len);
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43: case T4_COMPRESSION_T43:
return t43_decode_put(&s->decoder.t43, buf, len); return t43_decode_put(&s->decoder.t43, buf, len);
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_put(&s->decoder.t85, buf, len);
} }
return T4_DECODE_OK; return T4_DECODE_OK;
} }
@ -628,6 +669,23 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
} }
s->line_encoding = encoding; s->line_encoding = encoding;
return t4_t6_decode_set_encoding(&s->decoder.t4_t6, encoding); return t4_t6_decode_set_encoding(&s->decoder.t4_t6, encoding);
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
switch (s->line_encoding)
{
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
break;
default:
t85_decode_init(&s->decoder.t85, s->row_handler, s->row_handler_user_data);
/* Constrain received images to the maximum width of any FAX. This will
avoid one potential cause of trouble, where a bad received image has
a gigantic dimension that sucks our memory dry. */
t85_decode_set_image_size_constraints(&s->decoder.t85, T4_WIDTH_1200_A3, 0);
break;
}
s->line_encoding = encoding;
return 0;
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
switch (s->line_encoding) switch (s->line_encoding)
{ {
@ -660,23 +718,6 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
s->line_encoding = encoding; s->line_encoding = encoding;
return 0; return 0;
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
switch (s->line_encoding)
{
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
break;
default:
t85_decode_init(&s->decoder.t85, s->row_handler, s->row_handler_user_data);
/* Constrain received images to the maximum width of any FAX. This will
avoid one potential cause of trouble, where a bad received image has
a gigantic dimension that sucks our memory dry. */
t85_decode_set_image_size_constraints(&s->decoder.t85, T4_WIDTH_1200_A3, 0);
break;
}
s->line_encoding = encoding;
return 0;
} }
return -1; return -1;
} }
@ -698,15 +739,15 @@ SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_rx_state_t *s, t4_row_write_han
case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
return t4_t6_decode_set_row_write_handler(&s->decoder.t4_t6, handler, user_data); return t4_t6_decode_set_row_write_handler(&s->decoder.t4_t6, handler, user_data);
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_set_row_write_handler(&s->decoder.t85, handler, user_data);
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
return t42_decode_set_row_write_handler(&s->decoder.t42, handler, user_data); return t42_decode_set_row_write_handler(&s->decoder.t42, handler, user_data);
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43: case T4_COMPRESSION_T43:
return t43_decode_set_row_write_handler(&s->decoder.t43, handler, user_data); return t43_decode_set_row_write_handler(&s->decoder.t43, handler, user_data);
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_set_row_write_handler(&s->decoder.t85, handler, user_data);
} }
return -1; return -1;
} }
@ -717,6 +758,7 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
memset(t, 0, sizeof(*t)); memset(t, 0, sizeof(*t));
t->pages_transferred = s->current_page; t->pages_transferred = s->current_page;
t->pages_in_file = s->tiff.pages_in_file; t->pages_in_file = s->tiff.pages_in_file;
t->image_x_resolution = s->metadata.x_resolution; t->image_x_resolution = s->metadata.x_resolution;
t->image_y_resolution = s->metadata.y_resolution; t->image_y_resolution = s->metadata.y_resolution;
t->x_resolution = s->metadata.x_resolution; t->x_resolution = s->metadata.x_resolution;
@ -737,6 +779,16 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
t->bad_rows = s->decoder.t4_t6.bad_rows; t->bad_rows = s->decoder.t4_t6.bad_rows;
t->longest_bad_row_run = s->decoder.t4_t6.longest_bad_row_run; t->longest_bad_row_run = s->decoder.t4_t6.longest_bad_row_run;
break; break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t->type = T4_IMAGE_TYPE_BILEVEL;
t->width = t85_decode_get_image_width(&s->decoder.t85);
t->length = t85_decode_get_image_length(&s->decoder.t85);
t->image_type = t->type;
t->image_width = t->width;
t->image_length = t->length;
t->line_image_size = t85_decode_get_compressed_image_size(&s->decoder.t85)/8;
break;
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
t->type = 0; t->type = 0;
t->width = t42_decode_get_image_width(&s->decoder.t42); t->width = t42_decode_get_image_width(&s->decoder.t42);
@ -757,16 +809,6 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
t->line_image_size = t43_decode_get_compressed_image_size(&s->decoder.t43)/8; t->line_image_size = t43_decode_get_compressed_image_size(&s->decoder.t43)/8;
break; break;
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t->type = T4_IMAGE_TYPE_BILEVEL;
t->width = t85_decode_get_image_width(&s->decoder.t85);
t->length = t85_decode_get_image_length(&s->decoder.t85);
t->image_type = t->type;
t->image_width = t->width;
t->image_length = t->length;
t->line_image_size = t85_decode_get_compressed_image_size(&s->decoder.t85)/8;
break;
} }
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -782,6 +824,10 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
t4_t6_decode_restart(&s->decoder.t4_t6, s->image_width); t4_t6_decode_restart(&s->decoder.t4_t6, s->image_width);
break; break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t85_decode_restart(&s->decoder.t85);
break;
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
t42_decode_restart(&s->decoder.t42); t42_decode_restart(&s->decoder.t42);
break; break;
@ -790,10 +836,6 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
t43_decode_restart(&s->decoder.t43); t43_decode_restart(&s->decoder.t43);
break; break;
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t85_decode_restart(&s->decoder.t85);
break;
} }
s->line_image_size = 0; s->line_image_size = 0;
s->tiff.image_size = 0; s->tiff.image_size = 0;
@ -839,6 +881,11 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
t4_t6_decode_put(&s->decoder.t4_t6, NULL, 0); t4_t6_decode_put(&s->decoder.t4_t6, NULL, 0);
length = t4_t6_decode_get_image_length(&s->decoder.t4_t6); length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
break; break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t85_decode_put(&s->decoder.t85, NULL, 0);
length = t85_decode_get_image_length(&s->decoder.t85);
break;
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
t42_decode_put(&s->decoder.t42, NULL, 0); t42_decode_put(&s->decoder.t42, NULL, 0);
length = t42_decode_get_image_length(&s->decoder.t42); length = t42_decode_get_image_length(&s->decoder.t42);
@ -849,11 +896,6 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
length = t43_decode_get_image_length(&s->decoder.t43); length = t43_decode_get_image_length(&s->decoder.t43);
break; break;
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t85_decode_put(&s->decoder.t85, NULL, 0);
length = t85_decode_get_image_length(&s->decoder.t85);
break;
} }
if (length == 0) if (length == 0)
@ -939,15 +981,15 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s)
case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
return t4_t6_decode_release(&s->decoder.t4_t6); return t4_t6_decode_release(&s->decoder.t4_t6);
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_release(&s->decoder.t85);
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
return t42_decode_release(&s->decoder.t42); return t42_decode_release(&s->decoder.t42);
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43: case T4_COMPRESSION_T43:
return t43_decode_release(&s->decoder.t43); return t43_decode_release(&s->decoder.t43);
#endif #endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_release(&s->decoder.t85);
} }
return -1; return -1;
} }

View File

@ -94,8 +94,58 @@ typedef struct
int bit_mask; int bit_mask;
} t85_packer_t; } t85_packer_t;
typedef struct
{
float resolution;
int code;
} 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, int image_length);
static const res_table_t x_res_table[] =
{
//{ 100.0f/CM_PER_INCH, T4_X_RESOLUTION_100},
{ 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4},
//{ 200.0f/CM_PER_INCH, T4_X_RESOLUTION_200},
{ 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8},
{ 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300},
//{ 400.0f/CM_PER_INCH, T4_X_RESOLUTION_400},
{ 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16},
{ 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600},
{ 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800},
{1200.0f/CM_PER_INCH, T4_X_RESOLUTION_1200},
{ -1.00f, -1}
};
static const res_table_t y_res_table[] =
{
{ 38.50f, T4_Y_RESOLUTION_STANDARD},
//{ 100.0f/CM_PER_INCH, T4_Y_RESOLUTION_100},
{ 77.00f, T4_Y_RESOLUTION_FINE},
//{ 200.0f/CM_PER_INCH, T4_Y_RESOLUTION_200},
{ 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300},
{ 154.00f, T4_Y_RESOLUTION_SUPERFINE},
//{ 400.0f/CM_PER_INCH, T4_Y_RESOLUTION_400},
{ 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600},
{ 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800},
{1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200},
{ -1.00f, -1}
};
static const int resolution_map[10][10] =
{
{ 0, 0, 0, T4_RESOLUTION_R8_STANDARD, 0, 0, 0, 0, 0, 0},
{T4_RESOLUTION_100_100, 0, T4_RESOLUTION_200_100, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, T4_RESOLUTION_R8_FINE, 0, 0, 0, 0, 0, 0},
{ 0, 0, T4_RESOLUTION_200_200, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, T4_RESOLUTION_300_300, 0, 0, 0, 0, 0},
{ 0, 0, 0, T4_RESOLUTION_R8_SUPERFINE, 0, 0, T4_RESOLUTION_R16_SUPERFINE, 0, 0, 0},
{ 0, 0, T4_RESOLUTION_200_400, 0, 0, T4_RESOLUTION_400_400, 0, 0, 0, 0},
{ 0, 0, 0, 0, T4_RESOLUTION_300_600, 0, 0, T4_RESOLUTION_600_600, 0, 0},
{ 0, 0, 0, 0, 0, T4_RESOLUTION_400_800, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, T4_RESOLUTION_600_1200, 0, T4_RESOLUTION_1200_1200},
};
#if defined(SPANDSP_SUPPORT_TIFF_FX) #if defined(SPANDSP_SUPPORT_TIFF_FX)
/* TIFF-FX related extensions to the tag set supported by libtiff */ /* TIFF-FX related extensions to the tag set supported by libtiff */
@ -163,15 +213,39 @@ SPAN_DECLARE(void) TIFF_FX_init(void)
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
#endif #endif
static int test_resolution(int res_unit, float actual, float expected) static int match_resolution(int res_unit, float actual, const res_table_t table[])
{ {
int i;
int best_entry;
float best_ratio;
float ratio;
if (actual == 0.0f)
return -1;
if (res_unit == RESUNIT_INCH) if (res_unit == RESUNIT_INCH)
actual *= 1.0f/CM_PER_INCH; actual /= CM_PER_INCH;
return (expected*0.95f <= actual && actual <= expected*1.05f); best_ratio = 0.0f;
best_entry = -1;
for (i = 0; table[i].code > 0; i++)
{
if (actual > table[i].resolution)
ratio = table[i].resolution/actual;
else
ratio = actual/table[i].resolution;
if (ratio > best_ratio)
{
best_entry = i;
best_ratio = ratio;
}
}
if (best_ratio < 0.95f)
return -1;
return best_entry;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_SUPPORT_TIFF_FX) #if 0 //defined(SPANDSP_SUPPORT_TIFF_FX)
static int read_colour_map(t4_tx_state_t *s, int bits_per_sample) static int read_colour_map(t4_tx_state_t *s, int bits_per_sample)
{ {
int i; int i;
@ -220,36 +294,6 @@ static int read_colour_map(t4_tx_state_t *s, int bits_per_sample)
static int get_tiff_directory_info(t4_tx_state_t *s) static int get_tiff_directory_info(t4_tx_state_t *s)
{ {
static const struct
{
float resolution;
int code;
} x_res_table[] =
{
{ 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4},
{ 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8},
{ 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300},
{ 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16},
{ 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600},
{ 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800},
{1200.0f/CM_PER_INCH, T4_X_RESOLUTION_1200},
{ -1.00f, -1}
};
static const struct
{
float resolution;
int code;
} y_res_table[] =
{
{ 38.50f, T4_Y_RESOLUTION_STANDARD},
{ 77.00f, T4_Y_RESOLUTION_FINE},
{ 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300},
{ 154.00f, T4_Y_RESOLUTION_SUPERFINE},
{ 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600},
{ 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800},
{1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200},
{ -1.00f, -1}
};
#if defined(SPANDSP_SUPPORT_TIFF_FX) #if defined(SPANDSP_SUPPORT_TIFF_FX)
static const char *tiff_fx_fax_profiles[] = static const char *tiff_fx_fax_profiles[] =
{ {
@ -265,12 +309,12 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
char uu[10]; char uu[10];
uint64_t diroff; uint64_t diroff;
uint8_t parm8; uint8_t parm8;
uint16_t parm16;
#endif #endif
uint32_t parm32; uint32_t parm32;
int best_x_entry;
int best_y_entry;
float x_resolution; float x_resolution;
float y_resolution; float y_resolution;
int i;
t4_tx_tiff_state_t *t; t4_tx_tiff_state_t *t;
uint16_t bits_per_sample; uint16_t bits_per_sample;
uint16_t samples_per_pixel; uint16_t samples_per_pixel;
@ -324,36 +368,24 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
TIFFGetField(t->tiff_file, TIFFTAG_COMPRESSION, &t->compression); TIFFGetField(t->tiff_file, TIFFTAG_COMPRESSION, &t->compression);
t->fill_order = FILLORDER_LSB2MSB; t->fill_order = FILLORDER_LSB2MSB;
/* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the
precise value. The other value should be exact. */
/* Treat everything we can't match as R8. Most FAXes are this resolution anyway. */
s->metadata.x_resolution = T4_X_RESOLUTION_R8;
for (i = 0; x_res_table[i].code > 0; i++)
{
if (test_resolution(res_unit, x_resolution, x_res_table[i].resolution))
{
s->metadata.x_resolution = x_res_table[i].code;
break;
}
}
if (res_unit == RESUNIT_INCH) if (res_unit == RESUNIT_INCH)
t->image_x_resolution = x_resolution*100.0f/CM_PER_INCH; t->image_x_resolution = x_resolution*100.0f/CM_PER_INCH;
else else
t->image_x_resolution = x_resolution*100.0f; t->image_x_resolution = x_resolution*100.0f;
/* Treat everything we can't match as R8. Most FAXes are this resolution anyway. */
if ((best_x_entry = match_resolution(res_unit, x_resolution, x_res_table)) < 0)
best_x_entry = 3;
s->metadata.x_resolution = x_res_table[best_x_entry].code;
s->metadata.y_resolution = T4_Y_RESOLUTION_STANDARD;
for (i = 0; y_res_table[i].code > 0; i++)
{
if (test_resolution(res_unit, y_resolution, y_res_table[i].resolution))
{
s->metadata.y_resolution = y_res_table[i].code;
break;
}
}
if (res_unit == RESUNIT_INCH) if (res_unit == RESUNIT_INCH)
t->image_y_resolution = y_resolution*100.0f/CM_PER_INCH; t->image_y_resolution = y_resolution*100.0f/CM_PER_INCH;
else else
t->image_y_resolution = y_resolution*100.0f; t->image_y_resolution = y_resolution*100.0f;
if ((best_y_entry = match_resolution(res_unit, y_resolution, y_res_table)) < 0)
best_y_entry = 0;
s->metadata.y_resolution = y_res_table[best_y_entry].code;
//s->metadata.resolution_code = resolution_map[best_y_entry][best_x_entry];
t4_tx_set_image_width(s, s->image_width); t4_tx_set_image_width(s, s->image_width);
t4_tx_set_image_length(s, s->image_length); t4_tx_set_image_length(s, s->image_length);
@ -412,44 +444,15 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
static int test_tiff_directory_info(t4_tx_state_t *s) static int test_tiff_directory_info(t4_tx_state_t *s)
{ {
static const struct
{
float resolution;
int code;
} x_res_table[] =
{
{ 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4},
{ 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8},
{ 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300},
{ 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16},
{ 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600},
{ 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800},
{1200.0f/CM_PER_INCH, T4_X_RESOLUTION_1200},
{ -1.00f, -1}
};
static const struct
{
float resolution;
int code;
} y_res_table[] =
{
{ 38.50f, T4_Y_RESOLUTION_STANDARD},
{ 77.00f, T4_Y_RESOLUTION_FINE},
{ 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300},
{ 154.00f, T4_Y_RESOLUTION_SUPERFINE},
{ 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600},
{ 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800},
{1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200},
{ -1.00f, -1}
};
uint16_t res_unit; uint16_t res_unit;
uint32_t parm32; uint32_t parm32;
int best_x_entry;
int best_y_entry;
float x_resolution; float x_resolution;
float y_resolution; float y_resolution;
uint16_t bits_per_sample; uint16_t bits_per_sample;
uint16_t samples_per_pixel; uint16_t samples_per_pixel;
int image_type; int image_type;
int i;
t4_tx_tiff_state_t *t; t4_tx_tiff_state_t *t;
t = &s->tiff; t = &s->tiff;
@ -490,23 +493,17 @@ static int test_tiff_directory_info(t4_tx_state_t *s)
res_unit = RESUNIT_INCH; res_unit = RESUNIT_INCH;
TIFFGetField(t->tiff_file, TIFFTAG_RESOLUTIONUNIT, &res_unit); TIFFGetField(t->tiff_file, TIFFTAG_RESOLUTIONUNIT, &res_unit);
/* Allow a little range for the X resolution in centimeters. The spec doesn't pin down the
precise value. The other value should be exact. */
/* Treat everything we can't match as R8. Most FAXes are this resolution anyway. */ /* Treat everything we can't match as R8. Most FAXes are this resolution anyway. */
for (i = 0; x_res_table[i].code > 0; i++) if ((best_x_entry = match_resolution(res_unit, x_resolution, x_res_table)) < 0)
{
if (test_resolution(res_unit, x_resolution, x_res_table[i].resolution))
break;
}
if (s->metadata.x_resolution != x_res_table[i].code)
return 1; return 1;
for (i = 0; y_res_table[i].code > 0; i++) if (s->metadata.x_resolution != x_res_table[best_x_entry].code)
{
if (test_resolution(res_unit, y_resolution, y_res_table[i].resolution))
break;
}
if (s->metadata.y_resolution != y_res_table[i].code)
return 1; return 1;
if ((best_y_entry = match_resolution(res_unit, y_resolution, y_res_table)) < 0)
return 1;
if (s->metadata.y_resolution != y_res_table[best_y_entry].code)
return 1;
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/