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;
/*! \brief The common ground in compression schemes between the local and far ends. */
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;
/*! \brief The common group supported colour image resolutions. */
/*! \brief The common group of supported colour image 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. */
int line_encoding;
/*! \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:
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 */

View File

@ -82,6 +82,10 @@ typedef struct
int x_resolution;
/*! \brief Row-to-row (Y) resolution in pixels per metre on the wire. */
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;
/*!

View File

@ -98,11 +98,11 @@ enum
T30_SUPPORT_COMPRESSION_GRAYSCALE = 0x1000000,
/*! Colour support by multi-level codecs */
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,
/*! Convert a colour image to a gray-scale one */
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,
/*! Dither a colour image down a simple bilevel image, with rescaling to fit a FAX page */
T30_SUPPORT_COLOUR_TO_BILEVEL = 0x20000000,
@ -141,7 +141,7 @@ typedef enum
T4_X_RESOLUTION_200 = 7874,
T4_X_RESOLUTION_R8 = 8031,
T4_X_RESOLUTION_300 = 11811,
T4_X_RESOLUTION_400 = 15784,
T4_X_RESOLUTION_400 = 15748,
T4_X_RESOLUTION_R16 = 16063,
T4_X_RESOLUTION_600 = 23622,
T4_X_RESOLUTION_800 = 31496,
@ -176,27 +176,27 @@ enum
/*! Double FAX resolution 408dpi x 391dpi - bi-level only */
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,
/*! 200dpi x 100 dpi - bi-level only */
/*! 200dpi x 100dpi - bi-level only */
T4_RESOLUTION_200_100 = 6,
/*! 200dpi x 200 dpi */
/*! 200dpi x 200dpi */
T4_RESOLUTION_200_200 = 7,
/*! 200dpi x 400 dpi - bi-level only */
/*! 200dpi x 400dpi - bi-level only */
T4_RESOLUTION_200_400 = 8,
/*! 300dpi x 300 dpi */
/*! 300dpi x 300dpi */
T4_RESOLUTION_300_300 = 9,
/*! 300dpi x 600 dpi - bi-level only */
/*! 300dpi x 600dpi - bi-level only */
T4_RESOLUTION_300_600 = 10,
/*! 400dpi x 400 dpi */
/*! 400dpi x 400dpi */
T4_RESOLUTION_400_400 = 11,
/*! 400dpi x 800 dpi - bi-level only */
/*! 400dpi x 800dpi - bi-level only */
T4_RESOLUTION_400_800 = 12,
/*! 600dpi x 600 dpi */
/*! 600dpi x 600dpi */
T4_RESOLUTION_600_600 = 13,
/*! 600dpi x 1200 dpi - bi-level only */
/*! 600dpi x 1200dpi - bi-level only */
T4_RESOLUTION_600_1200 = 14,
/*! 1200dpi x 1200 dpi */
/*! 1200dpi x 1200dpi */
T4_RESOLUTION_1200_1200 = 15
};
@ -211,27 +211,27 @@ enum
/*! Support double FAX resolution 408dpi x 391dpi - bi-level only */
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,
/*! Support 200dpi x 100 dpi - bi-level only */
/*! Support 200dpi x 100dpi - bi-level only */
T4_SUPPORT_RESOLUTION_200_100 = 0x20,
/*! Support 200dpi x 200 dpi */
/*! Support 200dpi x 200dpi */
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,
/*! Support 300dpi x 300 dpi */
/*! Support 300dpi x 300dpi */
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,
/*! Support 400dpi x 400 dpi */
/*! Support 400dpi x 400dpi */
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,
/*! Support 600dpi x 600 dpi */
/*! Support 600dpi x 600dpi */
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,
/*! Support 1200dpi x 1200 dpi */
/*! Support 1200dpi x 1200dpi */
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.
\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. */
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.
\brief Get the logging context associated with a 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. */
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.
\param s The T.4 context.
\return The number of columns. */
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.
\param s The T.4 context.
\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 --------------------------------------------------------*/
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 i;
@ -1181,15 +1204,19 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* 215mm wide is always supported */
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))
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. */
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))
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. */
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))
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);
/* No custom illuminant */
@ -1275,10 +1302,6 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* No mode 26 (T.505) */
/* No digital network capability */
/* 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 RSA key management */
/* No override */
@ -1365,34 +1388,20 @@ int t30_build_dis_or_dtc(t30_state_t *s)
}
/*- 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)
{
int i;
int bad;
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
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 */
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. */
use_bilevel = TRUE;
switch (s->line_encoding)
{
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);
use_bilevel = FALSE;
break;
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
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);
use_bilevel = FALSE;
break;
#endif
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);
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 */
bad = T30_ERR_NORESSUPPORT;
row_squashing_ratio = 1;
switch (s->y_resolution)
if (use_bilevel)
{
case T4_Y_RESOLUTION_1200:
switch (s->x_resolution)
switch (s->y_resolution)
{
case T4_X_RESOLUTION_1200:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_1200_1200))
case T4_Y_RESOLUTION_1200:
switch (s->x_resolution)
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
bad = T30_ERR_OK;
case T4_X_RESOLUTION_1200:
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;
case T4_X_RESOLUTION_600:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_1200))
case T4_Y_RESOLUTION_800:
switch (s->x_resolution)
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
bad = T30_ERR_OK;
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);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
}
break;
}
break;
case T4_Y_RESOLUTION_800:
switch (s->x_resolution)
{
case T4_X_RESOLUTION_R16:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_800))
case T4_Y_RESOLUTION_600:
switch (s->x_resolution)
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
bad = T30_ERR_OK;
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);
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_600:
switch (s->x_resolution)
{
case T4_X_RESOLUTION_600:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_600))
case T4_Y_RESOLUTION_300:
switch (s->x_resolution)
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
bad = T30_ERR_OK;
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);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
bad = T30_ERR_OK;
}
break;
}
break;
case T4_X_RESOLUTION_300:
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_600))
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)
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
bad = T30_ERR_OK;
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_400))
{
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;
}
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))
else if (s->x_resolution == T4_X_RESOLUTION_R16 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
bad = T30_ERR_OK;
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R16_SUPERFINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
bad = T30_ERR_OK;
break;
}
}
break;
}
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))
else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_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;
break;
}
}
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))
else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_100)
{
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;
}
}
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;
}
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);
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)))
{
if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 1)
&&
(s->supported_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");
set_ctrl_bit(s->dcs_frame, 17);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
}
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)))
{
if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 2)
&&
(s->supported_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");
set_ctrl_bit(s->dcs_frame, 18);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
}
else
{
@ -1691,10 +1726,10 @@ static int build_dcs(t30_state_t *s)
/* Deal with the image length */
/* 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. */
if (test_ctrl_bit(s->far_dis_dtc_frame, 20))
set_ctrl_bit(s->dcs_frame, 20);
else if (test_ctrl_bit(s->far_dis_dtc_frame, 19))
set_ctrl_bit(s->dcs_frame, 19);
if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_UNLIMITED_LENGTH);
else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_B4))
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_B4_LENGTH);
if (s->error_correcting_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);
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);
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 */
s->octets_per_ecm_frame = 256;
/* Now we know if we are going to use ECM, select the compressions which we can use. */
s->mutual_compressions = s->supported_compressions;
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))
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))
{
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->y_resolution = -1;
//s->current_page_resolution = 0;
s->current_page_resolution = 0;
x = -1;
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->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_1200_1200;
s->current_page_resolution = T4_RESOLUTION_1200_1200;
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->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_600_600;
s->current_page_resolution = T4_RESOLUTION_600_600;
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->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_400_400;
s->current_page_resolution = T4_RESOLUTION_400_400;
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->y_resolution = T4_Y_RESOLUTION_300;
//s->current_page_resolution = T4_RESOLUTION_300_300;
s->current_page_resolution = T4_RESOLUTION_300_300;
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->y_resolution = T4_Y_RESOLUTION_200;
//s->current_page_resolution = T4_RESOLUTION_200_200;
s->current_page_resolution = T4_RESOLUTION_200_200;
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->y_resolution = T4_Y_RESOLUTION_100;
//s->current_page_resolution = T4_RESOLUTION_100_100;
s->current_page_resolution = T4_RESOLUTION_100_100;
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->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_1200_1200;
s->current_page_resolution = T4_RESOLUTION_1200_1200;
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->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_600_1200;
s->current_page_resolution = T4_RESOLUTION_600_1200;
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->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_600_600;
s->current_page_resolution = T4_RESOLUTION_600_600;
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->y_resolution = T4_Y_RESOLUTION_800;
//s->current_page_resolution = T4_RESOLUTION_400_800;
s->current_page_resolution = T4_RESOLUTION_400_800;
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->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_400_400;
s->current_page_resolution = T4_RESOLUTION_400_400;
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->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
//s->current_page_resolution = T4_RESOLUTION_R16_SUPERFINE;
s->current_page_resolution = T4_RESOLUTION_R16_SUPERFINE;
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->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_300_600;
s->current_page_resolution = T4_RESOLUTION_300_600;
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->y_resolution = T4_Y_RESOLUTION_300;
//s->current_page_resolution = T4_RESOLUTION_300_300;
s->current_page_resolution = T4_RESOLUTION_300_300;
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->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_200_400;
s->current_page_resolution = T4_RESOLUTION_200_400;
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->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
//s->current_page_resolution = T4_RESOLUTION_R8_SUPERFINE;
s->current_page_resolution = T4_RESOLUTION_R8_SUPERFINE;
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->y_resolution = T4_Y_RESOLUTION_200;
//s->current_page_resolution = T4_RESOLUTION_200_200;
s->current_page_resolution = T4_RESOLUTION_200_200;
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->y_resolution = T4_Y_RESOLUTION_FINE;
//s->current_page_resolution = T4_RESOLUTION_R8_FINE;
s->current_page_resolution = T4_RESOLUTION_R8_FINE;
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->y_resolution = T4_Y_RESOLUTION_100;
//s->current_page_resolution = T4_RESOLUTION_200_100;
s->current_page_resolution = T4_RESOLUTION_200_100;
x = 1;
}
else
{
s->x_resolution = T4_X_RESOLUTION_R8;
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;
}
}

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)
{
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);
return 0;
}

View File

@ -141,6 +141,45 @@ SPAN_DECLARE(const char *) t4_image_type_to_str(int type)
}
/*- 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)
{
time_t now;
@ -175,6 +214,10 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
case T4_COMPRESSION_T6:
output_compression = COMPRESSION_CCITT_T6;
break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
output_compression = COMPRESSION_T85;
break;
#if defined(SPANDSP_SUPPORT_T42)
case T4_COMPRESSION_T42_T81:
output_compression = COMPRESSION_JPEG;
@ -191,10 +234,6 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
photometric = PHOTOMETRIC_ITULAB;
break;
#endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
output_compression = COMPRESSION_T85;
break;
}
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_FAXMODE, FAXMODE_CLASSF);
break;
case COMPRESSION_T85:
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break;
case COMPRESSION_JPEG:
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break;
@ -216,9 +258,6 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
break;
#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_BITSPERSAMPLE, bits_per_sample);
@ -304,6 +343,10 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
case T4_COMPRESSION_T6:
s->image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
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:
s->image_length = t42_decode_get_image_length(&s->decoder.t42);
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);
break;
#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_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_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);
buf_len = 0;
buf = NULL;
@ -417,6 +457,7 @@ static int write_tiff_image(t4_rx_state_t *s)
break;
#if defined(SPANDSP_SUPPORT_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);
buf_len = 0;
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_T6:
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:
return t42_decode_put(&s->decoder.t42, buf, len);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
return t43_decode_put(&s->decoder.t43, buf, len);
#endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_put(&s->decoder.t85, buf, len);
}
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;
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:
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;
return 0;
#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;
}
@ -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_T6:
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:
return t42_decode_set_row_write_handler(&s->decoder.t42, handler, user_data);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
return t43_decode_set_row_write_handler(&s->decoder.t43, handler, user_data);
#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;
}
@ -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));
t->pages_transferred = s->current_page;
t->pages_in_file = s->tiff.pages_in_file;
t->image_x_resolution = s->metadata.x_resolution;
t->image_y_resolution = s->metadata.y_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->longest_bad_row_run = s->decoder.t4_t6.longest_bad_row_run;
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:
t->type = 0;
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;
break;
#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 --------------------------------------------------------*/
@ -782,6 +824,10 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
case T4_COMPRESSION_T6:
t4_t6_decode_restart(&s->decoder.t4_t6, s->image_width);
break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t85_decode_restart(&s->decoder.t85);
break;
case T4_COMPRESSION_T42_T81:
t42_decode_restart(&s->decoder.t42);
break;
@ -790,10 +836,6 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
t43_decode_restart(&s->decoder.t43);
break;
#endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t85_decode_restart(&s->decoder.t85);
break;
}
s->line_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);
length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
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:
t42_decode_put(&s->decoder.t42, NULL, 0);
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);
break;
#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)
@ -939,15 +981,15 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s)
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_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:
return t42_decode_release(&s->decoder.t42);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
return t43_decode_release(&s->decoder.t43);
#endif
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
return t85_decode_release(&s->decoder.t85);
}
return -1;
}

View File

@ -94,8 +94,58 @@ typedef struct
int bit_mask;
} 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 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)
/* 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 --------------------------------------------------------*/
#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)
actual *= 1.0f/CM_PER_INCH;
return (expected*0.95f <= actual && actual <= expected*1.05f);
actual /= CM_PER_INCH;
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 --------------------------------------------------------*/
#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)
{
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 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)
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];
uint64_t diroff;
uint8_t parm8;
uint16_t parm16;
#endif
uint32_t parm32;
int best_x_entry;
int best_y_entry;
float x_resolution;
float y_resolution;
int i;
t4_tx_tiff_state_t *t;
uint16_t bits_per_sample;
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);
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)
t->image_x_resolution = x_resolution*100.0f/CM_PER_INCH;
else
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)
t->image_y_resolution = y_resolution*100.0f/CM_PER_INCH;
else
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_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 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;
uint32_t parm32;
int best_x_entry;
int best_y_entry;
float x_resolution;
float y_resolution;
uint16_t bits_per_sample;
uint16_t samples_per_pixel;
int image_type;
int i;
t4_tx_tiff_state_t *t;
t = &s->tiff;
@ -490,23 +493,17 @@ static int test_tiff_directory_info(t4_tx_state_t *s)
res_unit = RESUNIT_INCH;
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. */
for (i = 0; x_res_table[i].code > 0; i++)
{
if (test_resolution(res_unit, x_resolution, x_res_table[i].resolution))
break;
}
if (s->metadata.x_resolution != x_res_table[i].code)
if ((best_x_entry = match_resolution(res_unit, x_resolution, x_res_table)) < 0)
return 1;
for (i = 0; y_res_table[i].code > 0; i++)
{
if (test_resolution(res_unit, y_resolution, y_res_table[i].resolution))
break;
}
if (s->metadata.y_resolution != y_res_table[i].code)
if (s->metadata.x_resolution != x_res_table[best_x_entry].code)
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;
}
/*- End of function --------------------------------------------------------*/