mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-09 21:14:02 +00:00
A cleanup of FAX image size/resolution matching accuracy. Squashing of bi-level
images should now be correct. This is now close to supporting grey scale and colour.
This commit is contained in:
@@ -78,7 +78,7 @@ EXTRA_DIST = floating_fudge.h \
|
||||
spandsp/private/README \
|
||||
spandsp/version.h.in
|
||||
|
||||
INCLUDES = -I$(top_builddir)
|
||||
AM_CPPFLAGS = -I$(top_builddir)
|
||||
|
||||
lib_LTLIBRARIES = libspandsp.la
|
||||
|
||||
|
||||
@@ -323,12 +323,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
||||
int supported_bilevel_resolutions,
|
||||
int supported_colour_resolutions);
|
||||
|
||||
/*! \brief Set the compression for the encoded data.
|
||||
\param s The T.4 context.
|
||||
\param encoding The encoding.
|
||||
\return 0 for success, otherwise -1. */
|
||||
SPAN_DECLARE(int) t4_tx_set_tx_encoding(t4_tx_state_t *s, int encoding);
|
||||
|
||||
/*! \brief Set the minimum number of encoded bits per row. This allows the
|
||||
makes the encoding process to be set to comply with the minimum row
|
||||
time specified by a remote receiving machine.
|
||||
@@ -336,11 +330,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_encoding(t4_tx_state_t *s, int encoding);
|
||||
\param bits The minimum number of bits per row. */
|
||||
SPAN_DECLARE(void) t4_tx_set_min_bits_per_row(t4_tx_state_t *s, int bits);
|
||||
|
||||
/*! \brief Set the width of the image.
|
||||
\param s The T.4 context.
|
||||
\param image_width The image width, in pixels. */
|
||||
SPAN_DECLARE(void) t4_tx_set_image_width(t4_tx_state_t *s, int image_width);
|
||||
|
||||
/*! \brief Set the maximum number of 2D encoded rows between 1D encoded rows. This
|
||||
is only valid for T.4 2D encoding.
|
||||
\param s The T.4 context.
|
||||
@@ -381,12 +370,6 @@ SPAN_DECLARE(void) t4_tx_set_header_overlays_image(t4_tx_state_t *s, int header_
|
||||
\return 0 for success, otherwise -1. */
|
||||
SPAN_DECLARE(int) t4_tx_set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler, void *user_data);
|
||||
|
||||
/*! \brief Set the row squashing ratio, for adjusting row-to-row (y) resolution of bi-level
|
||||
images for a T.4 transmit context.
|
||||
\param s The T.4 transmit context.
|
||||
\param row_squashing_ratio Vertical squashing ratio. */
|
||||
SPAN_DECLARE(void) t4_tx_set_row_squashing_ratio(t4_tx_state_t *s, int row_squashing_ratio);
|
||||
|
||||
/*! \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. */
|
||||
|
||||
+146
-268
@@ -1224,7 +1224,7 @@ int t30_build_dis_or_dtc(t30_state_t *s)
|
||||
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_3);
|
||||
//}
|
||||
|
||||
//if ((s->supported_compressions & (T4_COMPRESSION_COLOUR | T4_COMPRESSION_GRAYSCALE)))
|
||||
if ((s->supported_compressions & (T4_COMPRESSION_COLOUR | T4_COMPRESSION_GRAYSCALE)))
|
||||
{
|
||||
if ((s->supported_compressions & T4_COMPRESSION_COLOUR))
|
||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE);
|
||||
@@ -1249,8 +1249,8 @@ int t30_build_dis_or_dtc(t30_state_t *s)
|
||||
if ((s->supported_compressions & T4_COMPRESSION_12BIT))
|
||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE);
|
||||
|
||||
//if ((s->supported_compressions & T4_COMPRESSION_NO_SUBSAMPLING))
|
||||
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
|
||||
if ((s->supported_compressions & T4_COMPRESSION_NO_SUBSAMPLING))
|
||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
|
||||
|
||||
/* No custom illuminant */
|
||||
/* No custom gamut range */
|
||||
@@ -1423,8 +1423,6 @@ static int prune_dis_dtc(t30_state_t *s)
|
||||
static int build_dcs(t30_state_t *s)
|
||||
{
|
||||
int i;
|
||||
int bad;
|
||||
int row_squashing_ratio;
|
||||
int use_bilevel;
|
||||
int image_type;
|
||||
|
||||
@@ -1523,229 +1521,21 @@ static int build_dcs(t30_state_t *s)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the Y resolution bits */
|
||||
row_squashing_ratio = 1;
|
||||
bad = T30_ERR_NORESSUPPORT;
|
||||
if ((use_bilevel && (s->current_page_resolution & s->mutual_bilevel_resolutions))
|
||||
||
|
||||
(!use_bilevel && (s->current_page_resolution & s->mutual_colour_resolutions)))
|
||||
{
|
||||
/* The resolution is supported by both parties */
|
||||
switch (s->current_page_resolution)
|
||||
{
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
||||
break;
|
||||
case T4_RESOLUTION_200_100:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||
break;
|
||||
case T4_RESOLUTION_100_100:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100);
|
||||
break;
|
||||
case T4_RESOLUTION_R16_SUPERFINE:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
|
||||
break;
|
||||
case T4_RESOLUTION_R8_SUPERFINE:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
|
||||
break;
|
||||
case T4_RESOLUTION_R8_FINE:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||
break;
|
||||
case T4_RESOLUTION_R8_STANDARD:
|
||||
/* Nothing special to set */
|
||||
break;
|
||||
}
|
||||
bad = T30_ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
/* Deal with resolution fudging */
|
||||
if ((s->current_page_resolution & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
|
||||
{
|
||||
if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100)))
|
||||
{
|
||||
/* Fudge between imperial and metric */
|
||||
}
|
||||
}
|
||||
else if ((s->current_page_resolution & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100))
|
||||
{
|
||||
if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
|
||||
{
|
||||
/* Fudge between imperial and metric */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Deal with squashing options */
|
||||
if ((s->current_page_resolution & T4_RESOLUTION_R8_SUPERFINE))
|
||||
{
|
||||
if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_FINE))
|
||||
{
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||
row_squashing_ratio = 2;
|
||||
bad = T30_ERR_OK;
|
||||
}
|
||||
else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
|
||||
{
|
||||
row_squashing_ratio = 4;
|
||||
bad = T30_ERR_OK;
|
||||
}
|
||||
}
|
||||
else if ((s->current_page_resolution & T4_RESOLUTION_R8_FINE) && (s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
|
||||
{
|
||||
row_squashing_ratio = 2;
|
||||
bad = T30_ERR_OK;
|
||||
}
|
||||
else if ((s->current_page_resolution & T4_RESOLUTION_200_400))
|
||||
{
|
||||
if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_200))
|
||||
{
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||
row_squashing_ratio = 2;
|
||||
bad = T30_ERR_OK;
|
||||
}
|
||||
else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
|
||||
{
|
||||
row_squashing_ratio = 4;
|
||||
bad = T30_ERR_OK;
|
||||
}
|
||||
}
|
||||
else if ((s->current_page_resolution & T4_RESOLUTION_200_200) && (s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
|
||||
{
|
||||
row_squashing_ratio = 2;
|
||||
bad = T30_ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
t4_tx_set_row_squashing_ratio(&s->t4.tx, row_squashing_ratio);
|
||||
if (bad != T30_ERR_OK)
|
||||
{
|
||||
t30_set_status(s, bad);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Image resolution (%d x %d) not acceptable\n", s->x_resolution, s->y_resolution);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Deal with the image width. */
|
||||
/* Low (R4) res widths are not supported in recent versions of T.30 */
|
||||
bad = T30_ERR_OK;
|
||||
/* The following treats a width field of 11 like 10, which does what note 6 of Table 2/T.30
|
||||
says we should do with the invalid value 11. */
|
||||
if (((s->image_width == T4_WIDTH_200_A4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_300_A4) && (s->x_resolution == T4_X_RESOLUTION_300))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_400_A4) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_600_A4) && (s->x_resolution == T4_X_RESOLUTION_600))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
|
||||
/* Set the image width */
|
||||
switch (s->line_width_code)
|
||||
{
|
||||
case T4_SUPPORT_WIDTH_215MM:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
|
||||
/* No width related bits need to be set. */
|
||||
}
|
||||
else if (((s->image_width == T4_WIDTH_200_B4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_300_B4) && (s->x_resolution == T4_X_RESOLUTION_300))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_400_B4) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_600_B4) && (s->x_resolution == T4_X_RESOLUTION_600))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
|
||||
{
|
||||
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_255MM))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We do not support this width and resolution combination */
|
||||
bad = T30_ERR_NOSIZESUPPORT;
|
||||
}
|
||||
}
|
||||
else if (((s->image_width == T4_WIDTH_200_A3) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_300_A3) && (s->x_resolution == T4_X_RESOLUTION_300))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_400_A3) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_600_A3) && (s->x_resolution == T4_X_RESOLUTION_600))
|
||||
||
|
||||
((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200)))
|
||||
{
|
||||
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_303MM))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We do not support this width and resolution combination */
|
||||
bad = T30_ERR_NOSIZESUPPORT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We do not support this width and resolution combination */
|
||||
bad = T30_ERR_NOSIZESUPPORT;
|
||||
}
|
||||
|
||||
if (bad != T30_ERR_OK)
|
||||
{
|
||||
t30_set_status(s, bad);
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Image width (%d pixels) and resolution (%d x %d) is not an acceptable\n",
|
||||
s->image_width,
|
||||
s->x_resolution,
|
||||
s->y_resolution);
|
||||
return -1;
|
||||
break;
|
||||
case T4_SUPPORT_WIDTH_255MM:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
|
||||
break;
|
||||
case T4_SUPPORT_WIDTH_303MM:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the image length */
|
||||
@@ -1760,6 +1550,77 @@ static int build_dcs(t30_state_t *s)
|
||||
else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_US_LEGAL))
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NORTH_AMERICAN_LEGAL);
|
||||
|
||||
/* Set the Y resolution bits */
|
||||
switch (s->current_page_resolution)
|
||||
{
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
|
||||
break;
|
||||
case T4_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);
|
||||
break;
|
||||
case T4_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);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
||||
break;
|
||||
case T4_RESOLUTION_200_100:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||
break;
|
||||
case T4_RESOLUTION_100_100:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||
if (!use_bilevel)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100);
|
||||
break;
|
||||
case T4_RESOLUTION_R16_SUPERFINE:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
|
||||
break;
|
||||
case T4_RESOLUTION_R8_SUPERFINE:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
|
||||
break;
|
||||
case T4_RESOLUTION_R8_FINE:
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||
break;
|
||||
case T4_RESOLUTION_R8_STANDARD:
|
||||
/* Nothing special to set */
|
||||
break;
|
||||
}
|
||||
|
||||
if (s->error_correcting_mode)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_ECM_MODE);
|
||||
|
||||
@@ -1832,7 +1693,7 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
|
||||
if (!s->error_correcting_mode)
|
||||
{
|
||||
/* Remove any compression schemes which need error correction to work. */
|
||||
s->mutual_compressions &= (0xF0000000 | T4_COMPRESSION_NONE | T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D);
|
||||
s->mutual_compressions &= (0xFF800000 | T4_COMPRESSION_NONE | T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D);
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
|
||||
s->mutual_compressions &= ~T4_COMPRESSION_T4_2D;
|
||||
}
|
||||
@@ -1866,8 +1727,8 @@ static int analyze_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_12BIT_CAPABLE))
|
||||
s->mutual_compressions &= ~T4_COMPRESSION_12BIT;
|
||||
//if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
|
||||
// ???? = T4_COMPRESSION_T42_T81_SUBSAMPLING;
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
|
||||
s->mutual_compressions &= ~T4_COMPRESSION_NO_SUBSAMPLING;
|
||||
|
||||
/* bit74 custom illuminant */
|
||||
/* bit75 custom gamut range */
|
||||
@@ -2087,7 +1948,7 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
|
||||
|
||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING))
|
||||
{
|
||||
//???? = T4_COMPRESSION_T42_T81_SUBSAMPLING;
|
||||
//???? = T4_COMPRESSION_NO_SUBSAMPLING;
|
||||
}
|
||||
|
||||
if (!test_ctrl_bit(dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES))
|
||||
@@ -2529,7 +2390,6 @@ static int send_dcs_sequence(t30_state_t *s, int start)
|
||||
/* Schedule training after the messages */
|
||||
if (start)
|
||||
{
|
||||
prune_dcs(s);
|
||||
set_state(s, T30_STATE_D);
|
||||
s->step = 0;
|
||||
}
|
||||
@@ -2654,22 +2514,12 @@ static void set_min_scan_time(t30_state_t *s)
|
||||
{
|
||||
case T4_Y_RESOLUTION_SUPERFINE:
|
||||
case T4_Y_RESOLUTION_400:
|
||||
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
|
||||
{
|
||||
s->min_scan_time_code = translate_min_scan_time[(test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MIN_SCAN_TIME_HALVES)) ? 2 : 1][min_bits_field];
|
||||
break;
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support super-fine resolution. Squashing image.\n");
|
||||
/* Fall through */
|
||||
s->min_scan_time_code = translate_min_scan_time[(test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MIN_SCAN_TIME_HALVES)) ? 2 : 1][min_bits_field];
|
||||
break;
|
||||
case T4_Y_RESOLUTION_FINE:
|
||||
case T4_Y_RESOLUTION_200:
|
||||
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
|
||||
{
|
||||
s->min_scan_time_code = translate_min_scan_time[1][min_bits_field];
|
||||
break;
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support fine resolution. Squashing image.\n");
|
||||
/* Fall through */
|
||||
s->min_scan_time_code = translate_min_scan_time[1][min_bits_field];
|
||||
break;
|
||||
case T4_Y_RESOLUTION_STANDARD:
|
||||
case T4_Y_RESOLUTION_100:
|
||||
s->min_scan_time_code = translate_min_scan_time[0][min_bits_field];
|
||||
@@ -2689,6 +2539,8 @@ static void set_min_scan_time(t30_state_t *s)
|
||||
|
||||
static int start_sending_document(t30_state_t *s)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (s->tx_file[0] == '\0')
|
||||
{
|
||||
/* There is nothing to send */
|
||||
@@ -2703,27 +2555,68 @@ static int start_sending_document(t30_state_t *s)
|
||||
return -1;
|
||||
}
|
||||
s->operation_in_progress = OPERATION_IN_PROGRESS_T4_TX;
|
||||
t4_tx_get_pages_in_file(&s->t4.tx);
|
||||
t4_tx_set_tx_encoding(&s->t4.tx, s->line_compression);
|
||||
|
||||
t4_tx_set_local_ident(&s->t4.tx, s->tx_info.ident);
|
||||
t4_tx_set_header_info(&s->t4.tx, s->header_info);
|
||||
if (s->use_own_tz)
|
||||
t4_tx_set_header_tz(&s->t4.tx, &s->tz);
|
||||
|
||||
if (tx_start_page(s))
|
||||
t4_tx_get_pages_in_file(&s->t4.tx);
|
||||
|
||||
if ((res = t4_tx_set_tx_image_format(&s->t4.tx,
|
||||
s->mutual_compressions,
|
||||
s->mutual_image_sizes,
|
||||
s->mutual_bilevel_resolutions,
|
||||
s->mutual_colour_resolutions)) < 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Something seems to be wrong in the file\n");
|
||||
t30_set_status(s, T30_ERR_FILEERROR);
|
||||
switch (res)
|
||||
{
|
||||
case T4_IMAGE_FORMAT_INCOMPATIBLE:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image format\n");
|
||||
t30_set_status(s, T30_ERR_BADTIFFHDR);
|
||||
break;
|
||||
case T4_IMAGE_FORMAT_NOSIZESUPPORT:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image size\n");
|
||||
t30_set_status(s, T30_ERR_NOSIZESUPPORT);
|
||||
break;
|
||||
case T4_IMAGE_FORMAT_NORESSUPPORT:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image resolution\n");
|
||||
t30_set_status(s, T30_ERR_NORESSUPPORT);
|
||||
break;
|
||||
default:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image format\n");
|
||||
t30_set_status(s, T30_ERR_BADTIFF);
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
s->line_image_type = t4_tx_get_tx_image_type(&s->t4.tx);
|
||||
s->line_compression = t4_tx_get_tx_compression(&s->t4.tx);
|
||||
s->image_width = t4_tx_get_tx_image_width(&s->t4.tx);
|
||||
s->line_width_code = t4_tx_get_tx_image_width_code(&s->t4.tx);
|
||||
|
||||
s->x_resolution = t4_tx_get_tx_x_resolution(&s->t4.tx);
|
||||
s->y_resolution = t4_tx_get_tx_y_resolution(&s->t4.tx);
|
||||
s->image_width = t4_tx_get_tx_image_width(&s->t4.tx);
|
||||
/* The minimum scan time to be used can't be evaluated until we know the Y resolution, and
|
||||
must be evaluated before the minimum scan row bits can be evaluated. */
|
||||
s->current_page_resolution = t4_tx_get_tx_resolution(&s->t4.tx);
|
||||
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Choose image type %s (%d), compression %s (%d)\n",
|
||||
t4_image_type_to_str(s->line_image_type),
|
||||
s->line_image_type,
|
||||
t4_compression_to_str(s->line_compression),
|
||||
s->line_compression);
|
||||
|
||||
/* The minimum scan time to be used can't be evaluated until we know the Y resolution. */
|
||||
set_min_scan_time(s);
|
||||
|
||||
if (tx_start_page(s))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Something seems to be wrong in the file\n");
|
||||
t30_set_status(s, T30_ERR_BADTIFFHDR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->error_correcting_mode)
|
||||
{
|
||||
if (get_partial_ecm_page(s) == 0)
|
||||
@@ -2795,21 +2688,6 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
|
||||
send_dcn(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Choose a compression scheme from amongst those mutually available */
|
||||
if ((s->mutual_compressions & T4_COMPRESSION_T85_L0))
|
||||
s->line_compression = T4_COMPRESSION_T85_L0;
|
||||
else if ((s->mutual_compressions & T4_COMPRESSION_T85))
|
||||
s->line_compression = T4_COMPRESSION_T85;
|
||||
else if ((s->mutual_compressions & T4_COMPRESSION_T6))
|
||||
s->line_compression = T4_COMPRESSION_T6;
|
||||
else if ((s->mutual_compressions & T4_COMPRESSION_T4_2D))
|
||||
s->line_compression = T4_COMPRESSION_T4_2D;
|
||||
else
|
||||
s->line_compression = T4_COMPRESSION_T4_1D;
|
||||
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Choose compression %s (%d)\n", t4_compression_to_str(s->line_compression), s->line_compression);
|
||||
|
||||
if (s->phase_b_handler)
|
||||
{
|
||||
new_status = s->phase_b_handler(s, s->phase_b_user_data, msg[2]);
|
||||
@@ -6825,7 +6703,7 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
|
||||
| T4_SUPPORT_LENGTH_UNLIMITED;
|
||||
/* Set the output encoding to something safe. Most things get 1D and 2D
|
||||
encoding right. Quite a lot get other things wrong. */
|
||||
s->supported_output_compressions = T4_COMPRESSION_T4_2D;
|
||||
s->supported_output_compressions = T4_COMPRESSION_T4_2D | T4_COMPRESSION_T42_T81;
|
||||
s->local_min_scan_time_code = T30_MIN_SCAN_0MS;
|
||||
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||
span_log_set_protocol(&s->logging, "T.30");
|
||||
|
||||
+160
-94
@@ -234,11 +234,24 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T42)
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
output_compression = COMPRESSION_JPEG;
|
||||
bits_per_sample = 8;
|
||||
if (t->image_type == T4_IMAGE_TYPE_COLOUR_8BIT)
|
||||
{
|
||||
samples_per_pixel = 3;
|
||||
photometric = PHOTOMETRIC_YCBCR; //PHOTOMETRIC_ITULAB;
|
||||
}
|
||||
else
|
||||
{
|
||||
samples_per_pixel = 1;
|
||||
photometric = PHOTOMETRIC_MINISBLACK;
|
||||
}
|
||||
break;
|
||||
case T4_COMPRESSION_SYCC_T81:
|
||||
output_compression = COMPRESSION_JPEG;
|
||||
bits_per_sample = 8;
|
||||
samples_per_pixel = 3;
|
||||
photometric = PHOTOMETRIC_ITULAB;
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T43)
|
||||
@@ -288,6 +301,13 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
|
||||
if (t->compression == T4_COMPRESSION_T42_T81)
|
||||
{
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 2, 2);
|
||||
//TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 1, 1);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_JPEGQUALITY, 75);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
||||
}
|
||||
/* TIFFTAG_STRIPBYTECOUNTS and TIFFTAG_STRIPOFFSETS are added automatically */
|
||||
|
||||
x_resolution = s->metadata.x_resolution/100.0f;
|
||||
@@ -344,30 +364,32 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
||||
is always one greater than the highest page number in the file. */
|
||||
s->tiff.pages_in_file = s->current_page + 1;
|
||||
s->metadata.image_length = 0;
|
||||
switch (s->metadata.compression)
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
case T4_COMPRESSION_T4_2D:
|
||||
/* We only get bad row info from pages received in non-ECM mode. */
|
||||
if (output_compression == COMPRESSION_CCITT_T4)
|
||||
case 0:
|
||||
s->metadata.image_length = 1024;
|
||||
break;
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
if ((s->metadata.compression & (T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D)))
|
||||
{
|
||||
if (s->decoder.t4_t6.bad_rows)
|
||||
/* We only get bad row info from pages received in non-ECM mode. */
|
||||
if (output_compression == COMPRESSION_CCITT_T4)
|
||||
{
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_BADFAXLINES, s->decoder.t4_t6.bad_rows);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_CONSECUTIVEBADFAXLINES, s->decoder.t4_t6.longest_bad_row_run);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_REGENERATED);
|
||||
}
|
||||
else
|
||||
{
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN);
|
||||
if (s->decoder.t4_t6.bad_rows)
|
||||
{
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_BADFAXLINES, s->decoder.t4_t6.bad_rows);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_CONSECUTIVEBADFAXLINES, s->decoder.t4_t6.longest_bad_row_run);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_REGENERATED);
|
||||
}
|
||||
else
|
||||
{
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Fall through */
|
||||
case T4_COMPRESSION_T6:
|
||||
s->metadata.image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
|
||||
break;
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
|
||||
s->metadata.image_length = t85_decode_get_image_length(&s->decoder.t85);
|
||||
break;
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
@@ -401,6 +423,34 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
||||
/* Create a placeholder for the global parameters IFD, to be filled in later */
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_GLOBALPARAMETERSIFD, 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Paletised image? */
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_INDEXED, 1);
|
||||
/* T.44 mode */
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_MODENUMBER, 0);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 2\n");
|
||||
{
|
||||
float xxx[] = {20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0};
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_DECODE, (uint16) 2*samples_per_pixel, xxx);
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 3\n");
|
||||
{
|
||||
uint16_t xxx[] = {12, 34, 45, 67};
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_IMAGEBASECOLOR, (uint16_t) samples_per_pixel, xxx);
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 4\n");
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_T82OPTIONS, 0);
|
||||
{
|
||||
uint32_t xxx[] = {34, 56, 78, 90};
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_STRIPROWCOUNTS, (uint16_t) 5, xxx);
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 5\n");
|
||||
{
|
||||
uint32_t xxx[] = {2, 3};
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_IMAGELAYER, xxx);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -450,10 +500,10 @@ static int write_tiff_t85_image(t4_rx_state_t *s)
|
||||
if (buf_len < image_len + 65536)
|
||||
{
|
||||
buf_len += 65536;
|
||||
if ((buf2 = realloc(buf, buf_len)) == NULL)
|
||||
if ((buf2 = span_realloc(buf, buf_len)) == NULL)
|
||||
{
|
||||
if (buf)
|
||||
free(buf);
|
||||
span_free(buf);
|
||||
return -1;
|
||||
}
|
||||
buf = buf2;
|
||||
@@ -468,7 +518,7 @@ static int write_tiff_t85_image(t4_rx_state_t *s)
|
||||
return -1;
|
||||
}
|
||||
t85_encode_release(&t85);
|
||||
free(buf);
|
||||
span_free(buf);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
@@ -496,10 +546,10 @@ static int write_tiff_t43_image(t4_rx_state_t *s)
|
||||
if (buf_len < image_len + 65536)
|
||||
{
|
||||
buf_len += 65536;
|
||||
if ((buf2 = realloc(buf, buf_len)) == NULL)
|
||||
if ((buf2 = span_realloc(buf, buf_len)) == NULL)
|
||||
{
|
||||
if (buf)
|
||||
free(buf);
|
||||
span_free(buf);
|
||||
return -1;
|
||||
}
|
||||
buf = buf2;
|
||||
@@ -511,7 +561,7 @@ static int write_tiff_t43_image(t4_rx_state_t *s)
|
||||
if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, buf, image_len) < 0)
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file);
|
||||
t43_encode_release(&t43);
|
||||
free(buf);
|
||||
span_free(buf);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
@@ -525,49 +575,57 @@ static int write_tiff_image(t4_rx_state_t *s)
|
||||
#endif
|
||||
|
||||
t = &s->tiff;
|
||||
if (t->image_buffer == NULL || t->image_size <= 0)
|
||||
if (s->pre_encoded_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0))
|
||||
return -1;
|
||||
/* Set up the TIFF directory info... */
|
||||
set_tiff_directory_info(s);
|
||||
/* ...Put the directory in the file before the image data, to get them in the order specified
|
||||
for TIFF/F files... */
|
||||
if (!TIFFCheckpointDirectory(t->tiff_file))
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page);
|
||||
//if (!TIFFCheckpointDirectory(t->tiff_file))
|
||||
// span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page);
|
||||
/* ...and write out the image... */
|
||||
switch (t->compression)
|
||||
if (s->pre_encoded_ptr > 0)
|
||||
{
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t85_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->pre_encoded_buf, s->pre_encoded_ptr) < 0)
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (t->compression)
|
||||
{
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t85_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
case T4_COMPRESSION_T88:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t88_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case T4_COMPRESSION_T88:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t88_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T43)
|
||||
case T4_COMPRESSION_T43:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t43_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case T4_COMPRESSION_T43:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t43_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T45)
|
||||
case T4_COMPRESSION_T45:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t45_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case T4_COMPRESSION_T45:
|
||||
/* We need to perform this compression here, as libtiff does not understand it. */
|
||||
if (write_tiff_t45_image(s) < 0)
|
||||
return -1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Let libtiff do the compression */
|
||||
if (TIFFWriteEncodedStrip(t->tiff_file, 0, t->image_buffer, t->image_size) < 0)
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", t->file);
|
||||
break;
|
||||
default:
|
||||
/* Let libtiff do the compression */
|
||||
if (TIFFWriteEncodedStrip(t->tiff_file, 0, t->image_buffer, t->image_size) < 0)
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", t->file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* ...then finalise the directory entry, and libtiff is happy. */
|
||||
if (!TIFFWriteDirectory(t->tiff_file))
|
||||
@@ -633,7 +691,7 @@ static int close_tiff_output_file(t4_rx_state_t *s)
|
||||
put in it. */
|
||||
if (s->current_page == 0)
|
||||
remove(s->tiff.file);
|
||||
free((char *) s->tiff.file);
|
||||
span_free((char *) s->tiff.file);
|
||||
}
|
||||
s->tiff.file = NULL;
|
||||
return 0;
|
||||
@@ -646,7 +704,7 @@ static void tiff_rx_release(t4_rx_state_t *s)
|
||||
close_tiff_output_file(s);
|
||||
if (s->tiff.image_buffer)
|
||||
{
|
||||
free(s->tiff.image_buffer);
|
||||
span_free(s->tiff.image_buffer);
|
||||
s->tiff.image_buffer = NULL;
|
||||
s->tiff.image_size = 0;
|
||||
s->tiff.image_buffer_size = 0;
|
||||
@@ -673,10 +731,10 @@ SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len)
|
||||
if (s->pre_encoded_len < s->pre_encoded_ptr + 65536)
|
||||
{
|
||||
s->pre_encoded_len += 65536;
|
||||
if ((buf2 = realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL)
|
||||
if ((buf2 = span_realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL)
|
||||
{
|
||||
if (s->pre_encoded_buf)
|
||||
free(s->pre_encoded_buf);
|
||||
span_free(s->pre_encoded_buf);
|
||||
return -1;
|
||||
}
|
||||
s->pre_encoded_buf = buf2;
|
||||
@@ -757,11 +815,19 @@ static void select_tiff_compression(t4_rx_state_t *s, int output_image_type)
|
||||
else if ((s->supported_tiff_compressions & T4_COMPRESSION_T43))
|
||||
s->tiff.compression = T4_COMPRESSION_T43;
|
||||
}
|
||||
s->tiff.image_type = output_image_type;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
{
|
||||
#if 0
|
||||
output_image_type = T4_IMAGE_TYPE_BILEVEL;
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
s->current_decoder = 0;
|
||||
return 0;
|
||||
#else
|
||||
switch (compression)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
@@ -775,6 +841,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
break;
|
||||
default:
|
||||
t4_t6_decode_init(&s->decoder.t4_t6, compression, s->metadata.image_width, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6;
|
||||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
@@ -789,14 +856,15 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
break;
|
||||
default:
|
||||
t85_decode_init(&s->decoder.t85, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0;
|
||||
/* 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;
|
||||
}
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
return 0;
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
case T4_COMPRESSION_T88:
|
||||
@@ -805,10 +873,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
case T4_COMPRESSION_T88:
|
||||
break;
|
||||
default:
|
||||
t88_decode_init(&s->decoder.t88, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T88;
|
||||
break;
|
||||
}
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
return 0;
|
||||
#endif
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
@@ -820,6 +890,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
break;
|
||||
default:
|
||||
t42_decode_init(&s->decoder.t42, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T42_T81;
|
||||
/* 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. */
|
||||
@@ -837,6 +908,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
break;
|
||||
default:
|
||||
t43_decode_init(&s->decoder.t43, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T43;
|
||||
/* 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. */
|
||||
@@ -854,6 +926,8 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
case T4_COMPRESSION_T45:
|
||||
break;
|
||||
default:
|
||||
t45_decode_init(&s->decoder.t45, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T45;
|
||||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
@@ -863,6 +937,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
}
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
@@ -876,14 +951,11 @@ SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_rx_state_t *s, t4_row_write_han
|
||||
{
|
||||
s->row_handler = handler;
|
||||
s->row_handler_user_data = user_data;
|
||||
switch (s->metadata.compression)
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
case T4_COMPRESSION_T4_2D:
|
||||
case T4_COMPRESSION_T6:
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | 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:
|
||||
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
|
||||
return t85_decode_set_row_write_handler(&s->decoder.t85, handler, user_data);
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
case T4_COMPRESSION_T88:
|
||||
@@ -914,12 +986,11 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
|
||||
t->image_y_resolution = s->metadata.y_resolution;
|
||||
t->x_resolution = s->metadata.x_resolution;
|
||||
t->y_resolution = s->metadata.y_resolution;
|
||||
|
||||
t->compression = s->metadata.compression;
|
||||
switch (s->metadata.compression)
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
case T4_COMPRESSION_T4_2D:
|
||||
case T4_COMPRESSION_T6:
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
t->type = T4_IMAGE_TYPE_BILEVEL;
|
||||
t->width = t4_t6_decode_get_image_width(&s->decoder.t4_t6);
|
||||
t->length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
|
||||
@@ -930,8 +1001,7 @@ 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:
|
||||
case T4_COMPRESSION_T85 | 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);
|
||||
@@ -945,7 +1015,7 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
|
||||
break;
|
||||
#endif
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
t->type = T4_IMAGE_TYPE_COLOUR_8BIT; //T4_IMAGE_TYPE_GRAY_8BIT;
|
||||
t->type = T4_IMAGE_TYPE_GRAY_8BIT; //T4_IMAGE_TYPE_COLOUR_8BIT;
|
||||
t->width = t42_decode_get_image_width(&s->decoder.t42);
|
||||
t->length = t42_decode_get_image_length(&s->decoder.t42);
|
||||
t->image_type = t->type;
|
||||
@@ -976,21 +1046,18 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Start rx page %d - compression %s\n", s->current_page, t4_compression_to_str(s->metadata.compression));
|
||||
|
||||
switch (s->metadata.compression)
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case 0:
|
||||
s->pre_encoded_ptr = 0;
|
||||
s->pre_encoded_len = 0;
|
||||
s->image_put_handler = NULL;
|
||||
break;
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
case T4_COMPRESSION_T4_2D:
|
||||
case T4_COMPRESSION_T6:
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
t4_t6_decode_restart(&s->decoder.t4_t6, s->metadata.image_width);
|
||||
s->image_put_handler = (t4_image_put_handler_t) t4_t6_decode_put;
|
||||
break;
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
|
||||
t85_decode_restart(&s->decoder.t85);
|
||||
s->image_put_handler = (t4_image_put_handler_t) t85_decode_put;
|
||||
break;
|
||||
@@ -1036,7 +1103,7 @@ static int tiff_row_write_handler(void *user_data, const uint8_t buf[], size_t l
|
||||
{
|
||||
if (s->tiff.image_size + len >= s->tiff.image_buffer_size)
|
||||
{
|
||||
if ((t = realloc(s->tiff.image_buffer, s->tiff.image_buffer_size + 100*len)) == NULL)
|
||||
if ((t = span_realloc(s->tiff.image_buffer, s->tiff.image_buffer_size + 100*len)) == NULL)
|
||||
return -1;
|
||||
s->tiff.image_buffer_size += 100*len;
|
||||
s->tiff.image_buffer = t;
|
||||
@@ -1057,15 +1124,15 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
|
||||
if (s->image_put_handler)
|
||||
s->image_put_handler((void *) &s->decoder, NULL, 0);
|
||||
|
||||
switch (s->metadata.compression)
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
case T4_COMPRESSION_T4_2D:
|
||||
case T4_COMPRESSION_T6:
|
||||
case 0:
|
||||
length = s->pre_encoded_ptr;
|
||||
break;
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
|
||||
break;
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
|
||||
length = t85_decode_get_image_length(&s->decoder.t85);
|
||||
break;
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
@@ -1100,6 +1167,7 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
|
||||
if (write_tiff_image(s) == 0)
|
||||
s->current_page++;
|
||||
s->tiff.image_size = 0;
|
||||
s->pre_encoded_ptr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1142,6 +1210,7 @@ SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int
|
||||
s->metadata.y_resolution = T4_Y_RESOLUTION_FINE;
|
||||
|
||||
s->current_page = 0;
|
||||
s->current_decoder = 0;
|
||||
|
||||
/* Default handler */
|
||||
s->row_handler = tiff_row_write_handler;
|
||||
@@ -1153,7 +1222,7 @@ SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int
|
||||
if (open_tiff_output_file(s, file) < 0)
|
||||
{
|
||||
if (allocated)
|
||||
free(s);
|
||||
span_free(s);
|
||||
return NULL;
|
||||
}
|
||||
/* Save the file name for logging reports. */
|
||||
@@ -1167,14 +1236,11 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s)
|
||||
{
|
||||
if (s->tiff.file)
|
||||
tiff_rx_release(s);
|
||||
switch (s->metadata.compression)
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
case T4_COMPRESSION_T4_2D:
|
||||
case T4_COMPRESSION_T6:
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
return t4_t6_decode_release(&s->decoder.t4_t6);
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
|
||||
return t85_decode_release(&s->decoder.t85);
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
case T4_COMPRESSION_T88:
|
||||
@@ -1200,7 +1266,7 @@ SPAN_DECLARE(int) t4_rx_free(t4_rx_state_t *s)
|
||||
int ret;
|
||||
|
||||
ret = t4_rx_release(s);
|
||||
free(s);
|
||||
span_free(s);
|
||||
return ret;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
+1221
-236
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user