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. */
/* 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 */
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;
/*!
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,
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,
/*! 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
};
/*! 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
};
/*! 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.
\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. */
}
/*- 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;
/* 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);
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 */
/* 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 */
}
/*- 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. */
/* 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:
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);
- bad = T30_ERR_OK;
- break;
+ 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_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_R8 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
{
- set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
- bad = T30_ERR_OK;
- break;
+ 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;
+ }
}
- }
- 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))
+ 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)
{
- set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
- bad = T30_ERR_OK;
- break;
+ 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_SUPERFINE)
- {
- if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R8_SUPERFINE))
+ else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_FINE)
{
- set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
- bad = T30_ERR_OK;
- break;
+ 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 */
- 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))
+ 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)
{
- set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
+ /* No bits to set for this */
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))
+ 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_200_200);
+ set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
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)
{
||
((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
{
||
((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
{
/* 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);
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)
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):
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))
{
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
{
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;
}
}
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;
}
}
/*- 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;
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;
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);
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;
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);
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;
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);
{
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;
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;
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;
}
}
s->line_encoding = encoding;
return t4_t6_decode_set_encoding(&s->decoder.t4_t6, encoding);
- case T4_COMPRESSION_T42_T81:
+ case T4_COMPRESSION_T85:
+ case T4_COMPRESSION_T85_L0:
switch (s->line_encoding)
{
- case T4_COMPRESSION_T42_T81:
+ case T4_COMPRESSION_T85:
+ case T4_COMPRESSION_T85_L0:
break;
default:
- t42_decode_init(&s->decoder.t42, s->row_handler, s->row_handler_user_data);
+ 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. */
- t42_decode_set_image_size_constraints(&s->decoder.t42, T4_WIDTH_1200_A3, 0);
+ t85_decode_set_image_size_constraints(&s->decoder.t85, T4_WIDTH_1200_A3, 0);
break;
}
s->line_encoding = encoding;
return 0;
-#if defined(SPANDSP_SUPPORT_T43)
- case T4_COMPRESSION_T43:
+ case T4_COMPRESSION_T42_T81:
switch (s->line_encoding)
{
- case T4_COMPRESSION_T43:
+ case T4_COMPRESSION_T42_T81:
break;
default:
- t43_decode_init(&s->decoder.t43, s->row_handler, s->row_handler_user_data);
+ t42_decode_init(&s->decoder.t42, 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. */
- t43_decode_set_image_size_constraints(&s->decoder.t43, T4_WIDTH_1200_A3, 0);
+ t42_decode_set_image_size_constraints(&s->decoder.t42, T4_WIDTH_1200_A3, 0);
break;
}
s->line_encoding = encoding;
return 0;
-#endif
- case T4_COMPRESSION_T85:
- case T4_COMPRESSION_T85_L0:
+#if defined(SPANDSP_SUPPORT_T43)
+ case T4_COMPRESSION_T43:
switch (s->line_encoding)
{
- case T4_COMPRESSION_T85:
- case T4_COMPRESSION_T85_L0:
+ case T4_COMPRESSION_T43:
break;
default:
- t85_decode_init(&s->decoder.t85, s->row_handler, s->row_handler_user_data);
+ t43_decode_init(&s->decoder.t43, 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);
+ t43_decode_set_image_size_constraints(&s->decoder.t43, T4_WIDTH_1200_A3, 0);
break;
}
s->line_encoding = encoding;
return 0;
+#endif
}
return -1;
}
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;
}
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;
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);
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 --------------------------------------------------------*/
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;
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;
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);
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)
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;
}
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 */
/*- 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;
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[] =
{
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;
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);
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;
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 --------------------------------------------------------*/