Spandspi's FAX engine now gives separate size and resolution information about

the images on the line and the images in the file. The ties in with the recent
addition of image resizing and flattenign for colur images.
mod_spandsp has been changed to make use of the additional information.
This commit is contained in:
Steve Underwood 2013-03-10 20:55:21 +08:00
parent d9a4b8a9b0
commit 45eaaf4178
14 changed files with 172 additions and 44 deletions

View File

@ -218,6 +218,8 @@ struct t30_state_s
/*! \brief TRUE if a local T.30 interrupt is pending. */
int local_interrupt_pending;
/*! \brief The image coding to be used on the line for non-bilevel images. */
int multilevel_line_encoding;
/*! \brief The image coding being used on the line. */
int line_encoding;
/*! \brief The image coding being used for output files. */

View File

@ -57,9 +57,15 @@ typedef struct
/*! \brief Row counter for playing out the rows of the image. */
int row;
/*! \brief Image length of the image in the file. This is used when the
image is resized or dithered flat. */
/*! \brief Width of the image in the file. */
int image_width;
/*! \brief Length of the image in the file. */
int image_length;
/*! \brief Column-to-column (X) resolution in pixels per metre of the image in the file. */
int image_x_resolution;
/*! \brief Row-to-row (Y) resolution in pixels per metre of the image in the file. */
int image_y_resolution;
/*! \brief Row counter used when the image is resized or dithered flat. */
int raw_row;
} t4_tx_tiff_state_t;
@ -72,9 +78,9 @@ typedef struct
*/
typedef struct
{
/*! \brief Column-to-column (X) resolution in pixels per metre. */
/*! \brief Column-to-column (X) resolution in pixels per metre on the wire. */
int x_resolution;
/*! \brief Row-to-row (Y) resolution in pixels per metre. */
/*! \brief Row-to-row (Y) resolution in pixels per metre on the wire. */
int y_resolution;
} t4_tx_metadata_t;

View File

@ -369,7 +369,7 @@ static __inline__ int16_t saturated_mul16(int16_t a, int16_t b)
if (product == 0x40000000)
return INT16_MAX;
/*endif*/
return (int16_t)(product >> 15);
return (int16_t) (product >> 15);
}
/*- End of function --------------------------------------------------------*/

View File

@ -531,13 +531,25 @@ typedef struct
int pages_rx;
/*! \brief The number of pages in the file (<0 if not known). */
int pages_in_file;
/*! \brief The horizontal column-to-column resolution of the most recent page, in pixels per metre */
/*! \brief The type of image of the most recent file page */
int image_type;
/*! \brief The horizontal column-to-column resolution of the most recent file page, in pixels per metre */
int image_x_resolution;
/*! \brief The vertical row-to-row resolution of the most recent file page, in pixels per metre */
int image_y_resolution;
/*! \brief The number of horizontal pixels in the most recent file page. */
int image_width;
/*! \brief The number of vertical pixels in the most recent file page. */
int image_length;
/*! \brief The type of image of the most recent exchanged page */
int type;
/*! \brief The horizontal column-to-column resolution of the most recent exchanged page, in pixels per metre */
int x_resolution;
/*! \brief The vertical row-to-row resolution of the most recent page, in pixels per metre */
/*! \brief The vertical row-to-row resolution of the most recent exchanged page, in pixels per metre */
int y_resolution;
/*! \brief The number of horizontal pixels in the most recent page. */
/*! \brief The number of horizontal pixels in the most recent exchanged page. */
int width;
/*! \brief The number of vertical pixels in the most recent page. */
/*! \brief The number of vertical pixels in the most recent exchanged page. */
int length;
/*! \brief The size of the image, in bytes */
int image_size;

View File

@ -232,18 +232,30 @@ typedef struct
int pages_transferred;
/*! \brief The number of pages in the file (<0 if unknown). */
int pages_in_file;
/*! \brief The number of horizontal pixels in the most recent page. */
int width;
/*! \brief The number of vertical pixels in the most recent page. */
int length;
/*! \brief The number of bad pixel rows in the most recent page. */
int bad_rows;
/*! \brief The largest number of bad pixel rows in a block in the most recent page. */
int longest_bad_row_run;
/*! \brief The horizontal resolution of the page in pixels per metre */
/*! \brief The type of image in the file page */
int image_type;
/*! \brief The horizontal resolution of the file page in pixels per metre */
int image_x_resolution;
/*! \brief The vertical resolution of the file page in pixels per metre */
int image_y_resolution;
/*! \brief The number of horizontal pixels in the file page. */
int image_width;
/*! \brief The number of vertical pixels in the file page. */
int image_length;
/*! \brief The type of image in the exchanged page */
int type;
/*! \brief The horizontal resolution of the exchanged page in pixels per metre */
int x_resolution;
/*! \brief The vertical resolution of the page in pixels per metre */
/*! \brief The vertical resolution of the exchanged page in pixels per metre */
int y_resolution;
/*! \brief The number of horizontal pixels in the exchanged page. */
int width;
/*! \brief The number of vertical pixels in the exchanged page. */
int length;
/*! \brief The type of compression used between the FAX machines */
int encoding;
/*! \brief The size of the image on the line, in bytes */
@ -369,6 +381,12 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
\return A pointer to the string. */
SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding);
/*! Get the short text name of an image format.
\brief Get the short text name of an image format.
\param encoding The image format.
\return A pointer to the string. */
SPAN_DECLARE(const char *) t4_image_type_to_str(int type);
#if defined(__cplusplus)
}
#endif

View File

@ -6313,12 +6313,21 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t)
t->pages_tx = s->tx_page_number;
t->pages_rx = s->rx_page_number;
t->pages_in_file = stats.pages_in_file;
t->width = stats.width;
t->length = stats.length;
t->bad_rows = stats.bad_rows;
t->longest_bad_row_run = stats.longest_bad_row_run;
t->image_type = stats.image_type;
t->image_x_resolution = stats.image_x_resolution;
t->image_y_resolution = stats.image_y_resolution;
t->image_width = stats.image_width;
t->image_length = stats.image_length;
t->type = stats.type;
t->x_resolution = stats.x_resolution;
t->y_resolution = stats.y_resolution;
t->width = stats.width;
t->length = stats.length;
t->encoding = stats.encoding;
t->image_size = stats.line_image_size;
t->current_status = s->current_status;

View File

@ -114,6 +114,27 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(const char *) t4_image_type_to_str(int type)
{
switch (type)
{
case T4_IMAGE_TYPE_BILEVEL:
return "bi-level";
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
return "bi-level colour";
case T4_IMAGE_TYPE_GRAY_8BIT:
return "8-bit gray scale";
case T4_IMAGE_TYPE_GRAY_12BIT:
return "12-bit gray scale";
case T4_IMAGE_TYPE_COLOUR_8BIT:
return "8-bit colour";
case T4_IMAGE_TYPE_COLOUR_12BIT:
return "12-bit colour";
}
return "???";
}
/*- End of function --------------------------------------------------------*/
static int set_tiff_directory_info(t4_rx_state_t *s)
{
time_t now;
@ -573,6 +594,8 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
memset(t, 0, sizeof(*t));
t->pages_transferred = s->current_page;
t->pages_in_file = s->tiff.pages_in_file;
t->image_x_resolution = s->metadata.x_resolution;
t->image_y_resolution = s->metadata.y_resolution;
t->x_resolution = s->metadata.x_resolution;
t->y_resolution = s->metadata.y_resolution;
t->encoding = s->line_encoding;
@ -581,28 +604,44 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
case T4_COMPRESSION_ITU_T4_1D:
case T4_COMPRESSION_ITU_T4_2D:
case T4_COMPRESSION_ITU_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);
t->image_type = t->type;
t->image_width = t->width;
t->image_length = t->length;
t->line_image_size = t4_t6_decode_get_compressed_image_size(&s->decoder.t4_t6)/8;
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_ITU_T42:
t->type = 0;
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;
t->image_width = t->width;
t->image_length = t->length;
t->line_image_size = t42_decode_get_compressed_image_size(&s->decoder.t42)/8;
break;
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_ITU_T43:
t->type = 0;
t->width = t43_decode_get_image_width(&s->decoder.t43);
t->length = t43_decode_get_image_length(&s->decoder.t43);
t->image_type = t->type;
t->image_width = t->width;
t->image_length = t->length;
t->line_image_size = t43_decode_get_compressed_image_size(&s->decoder.t43)/8;
break;
#endif
case T4_COMPRESSION_ITU_T85:
case T4_COMPRESSION_ITU_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;
}

View File

@ -289,10 +289,11 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
#endif
parm32 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
t->image_width =
s->image_width = parm32;
parm32 = 0;
TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32);
s->tiff.image_length =
t->image_length =
s->image_length = parm32;
x_resolution = 0.0f;
TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);
@ -322,6 +323,10 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
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;
s->metadata.y_resolution = T4_Y_RESOLUTION_STANDARD;
for (i = 0; y_res_table[i].code > 0; i++)
@ -332,6 +337,11 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
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;
t4_tx_set_image_width(s, s->image_width);
t4_tx_set_image_length(s, s->image_length);
t4_tx_set_max_2d_rows_per_1d_row(s, -s->metadata.y_resolution);
@ -421,7 +431,7 @@ static int test_tiff_directory_info(t4_tx_state_t *s)
if (t->image_type != T4_IMAGE_TYPE_BILEVEL)
return -1;
#endif
if (s->tiff.image_type != image_type)
if (t->image_type != image_type)
return 1;
parm32 = 0;
@ -984,6 +994,13 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t
memset(t, 0, sizeof(*t));
t->pages_transferred = s->current_page - s->start_page;
t->pages_in_file = s->tiff.pages_in_file;
t->image_type = s->tiff.image_type;
t->image_width = s->tiff.image_width;
t->image_length = s->tiff.image_length;
t->image_x_resolution = s->tiff.image_x_resolution;
t->image_y_resolution = s->tiff.image_y_resolution;
t->x_resolution = s->metadata.x_resolution;
t->y_resolution = s->metadata.y_resolution/s->row_squashing_ratio;
t->encoding = s->line_encoding;
@ -992,26 +1009,30 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t
case T4_COMPRESSION_ITU_T4_1D:
case T4_COMPRESSION_ITU_T4_2D:
case T4_COMPRESSION_ITU_T6:
t->type = T4_IMAGE_TYPE_BILEVEL;
t->width = t4_t6_encode_get_image_width(&s->encoder.t4_t6);
t->length = t4_t6_encode_get_image_length(&s->encoder.t4_t6);
t->length = t4_t6_encode_get_image_length(&s->encoder.t4_t6)/s->row_squashing_ratio;
t->line_image_size = t4_t6_encode_get_compressed_image_size(&s->encoder.t4_t6)/8;
break;
case T4_COMPRESSION_ITU_T42:
t->type = 0;
t->width = t42_encode_get_image_width(&s->encoder.t42);
t->length = t42_encode_get_image_length(&s->encoder.t42);
t->length = t42_encode_get_image_length(&s->encoder.t42)/s->row_squashing_ratio;
t->line_image_size = t42_encode_get_compressed_image_size(&s->encoder.t42)/8;
break;
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_ITU_T43:
t->type = 0;
t->width = t43_encode_get_image_width(&s->encoder.t43);
t->length = t43_encode_get_image_length(&s->encoder.t43);
t->length = t43_encode_get_image_length(&s->encoder.t43)/s->row_squashing_ratio;
t->line_image_size = t43_encode_get_compressed_image_size(&s->encoder.t43)/8;
break;
#endif
case T4_COMPRESSION_ITU_T85:
case T4_COMPRESSION_ITU_T85_L0:
t->type = T4_IMAGE_TYPE_BILEVEL;
t->width = t85_encode_get_image_width(&s->encoder.t85);
t->length = t85_encode_get_image_length(&s->encoder.t85);
t->length = t85_encode_get_image_length(&s->encoder.t85)/s->row_squashing_ratio;
t->line_image_size = t85_encode_get_compressed_image_size(&s->encoder.t85)/8;
break;
}

View File

@ -63,7 +63,7 @@ int main(int argc, char *argv[])
exit(2);
}
gen = dtmf_tx_init(NULL);
gen = dtmf_tx_init(NULL, NULL, NULL);
len = dtmf_tx(gen, amp, 16384);
printf("Generated %d samples\n", len);
sf_writef_short(outhandle, amp, len);
@ -117,7 +117,7 @@ int main(int argc, char *argv[])
}
while (len > 0);
dtmf_tx_init(gen);
dtmf_tx_init(gen, NULL, NULL);
len = dtmf_tx(gen, amp, 16384);
printf("Generated %d samples\n", len);
sf_writef_short(outhandle, amp, len);

View File

@ -83,14 +83,17 @@ struct faxtester_state_s
int image_len;
int image_ptr;
int image_bit_ptr;
int ecm_frame_size;
int corrupt_crc;
int final_delayed;
fax_modems_state_t modems;
/*! \brief CED or CNG detector */
modem_connect_tones_rx_state_t connect_rx;
/*! If TRUE, transmission is in progress */
int transmit;

View File

@ -529,7 +529,7 @@ int main(int argc, char *argv[])
decode_file_name = NULL;
code_to_look_up = -1;
t38_transport = T38_TRANSPORT_UDPTL;
while ((opt = getopt(argc, argv, "c:d:D:efFgH:i:Ilm:M:n:p:s:tT:u:v:z:")) != -1)
while ((opt = getopt(argc, argv, "c:d:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1)
{
switch (opt)
{
@ -865,7 +865,7 @@ int main(int argc, char *argv[])
T30_SUPPORT_T4_1D_COMPRESSION
| T30_SUPPORT_T4_2D_COMPRESSION
| T30_SUPPORT_T6_COMPRESSION
| T30_SUPPORT_T81_COMPRESSION
//| T30_SUPPORT_T81_COMPRESSION
| T30_SUPPORT_T85_COMPRESSION
| T30_SUPPORT_T85_L0_COMPRESSION);
}

View File

@ -105,8 +105,9 @@ void fax_log_page_transfer_statistics(t30_state_t *s, const char *tag)
printf("%s: Bad ECM frames %d\n", tag, t.error_correcting_mode_retries);
printf("%s: Compression type %s (%d)\n", tag, t4_encoding_to_str(t.encoding), t.encoding);
printf("%s: Compressed image size %d bytes\n", tag, t.image_size);
printf("%s: Image size %d pels x %d pels\n", tag, t.width, t.length);
printf("%s: Image resolution %d pels/m x %d pels/m\n", tag, t.x_resolution, t.y_resolution);
printf("%s: Image type %s (%s in the file)\n", tag, t4_image_type_to_str(t.type), t4_image_type_to_str(t.image_type));
printf("%s: Image size %d pels x %d pels (%d pels x %d pels in the file)\n", tag, t.width, t.length, t.image_width, t.image_length);
printf("%s: Image resolution %d pels/m x %d pels/m (%d pels/m x %d pels/m in the file)\n", tag, t.x_resolution, t.y_resolution, t.image_x_resolution, t.image_y_resolution);
#if defined(SPANDSP_EXPOSE_INTERNAL_STRUCTURES)
printf("%s: Bits per row - min %d, max %d\n", tag, s->t4.tx.encoder.t4_t6.min_row_bits, s->t4.tx.encoder.t4_t6.max_row_bits);
#endif

View File

@ -130,7 +130,9 @@ static void display_page_stats(t4_rx_state_t *s)
printf("Pages = %d\n", stats.pages_transferred);
printf("Compression = %s\n", t4_encoding_to_str(stats.encoding));
printf("Compressed size = %d\n", stats.line_image_size);
printf("Raw image size = %d pels x %d pels\n", stats.image_width, stats.image_length);
printf("Image size = %d pels x %d pels\n", stats.width, stats.length);
printf("Raw image resolution = %d pels/m x %d pels/m\n", stats.image_x_resolution, stats.image_y_resolution);
printf("Image resolution = %d pels/m x %d pels/m\n", stats.x_resolution, stats.y_resolution);
printf("Bad rows = %d\n", stats.bad_rows);
printf("Longest bad row run = %d\n", stats.longest_bad_row_run);

View File

@ -358,9 +358,11 @@ static int phase_b_handler(t30_state_t *s, void *user_data, int result)
static int phase_d_handler(t30_state_t *s, void *user_data, int msg)
{
t30_stats_t t30_stats;
char *fax_image_resolution = NULL;
char *fax_file_image_resolution = NULL;
char *fax_line_image_resolution = NULL;
char *fax_file_image_pixel_size = NULL;
char *fax_line_image_pixel_size = NULL;
char *fax_image_size = NULL;
char *fax_image_pixel_size = NULL;
char *fax_bad_rows = NULL;
char *fax_encoding = NULL;
char *fax_longest_bad_row_run = NULL;
@ -383,14 +385,24 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg)
/* Set Channel Variable */
fax_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.x_resolution, t30_stats.y_resolution);
if (fax_image_resolution) {
switch_channel_set_variable(channel, "fax_image_resolution", fax_image_resolution);
fax_line_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.x_resolution, t30_stats.y_resolution);
if (fax_line_image_resolution) {
switch_channel_set_variable(channel, "fax_image_resolution", fax_line_image_resolution);
}
fax_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.width, t30_stats.length);
if (fax_image_pixel_size) {
switch_channel_set_variable(channel, "fax_image_pixel_size", fax_image_pixel_size);;
fax_file_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.image_x_resolution, t30_stats.image_y_resolution);
if (fax_file_image_resolution) {
switch_channel_set_variable(channel, "fax_file_image_resolution", fax_file_image_resolution);
}
fax_line_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.width, t30_stats.length);
if (fax_line_image_pixel_size) {
switch_channel_set_variable(channel, "fax_image_pixel_size", fax_line_image_pixel_size);;
}
fax_file_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.image_width, t30_stats.image_length);
if (fax_file_image_pixel_size) {
switch_channel_set_variable(channel, "fax_file_image_pixel_size", fax_file_image_pixel_size);;
}
fax_image_size = switch_core_session_sprintf(session, "%d", t30_stats.image_size);
@ -423,8 +435,9 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==== Page %s===========================================================\n", pvt->app_mode == FUNCTION_TX ? "Sent ====": "Received ");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Page no = %d\n", (pvt->app_mode == FUNCTION_TX) ? t30_stats.pages_tx : t30_stats.pages_rx);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image size = %d x %d pixels\n", t30_stats.width, t30_stats.length);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image resolution = %d/m x %d/m\n", t30_stats.x_resolution, t30_stats.y_resolution);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image type = %s (%s in the file)\n", t4_image_type_to_str(t30_stats.type), t4_image_type_to_str(t30_stats.image_type));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image size = %d x %d pixels (%d x %d pixels in the file)\n", t30_stats.width, t30_stats.length, t30_stats.image_width, t30_stats.image_length);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image resolution = %d/m x %d/m (%d/m x %d/m in the file)\n", t30_stats.x_resolution, t30_stats.y_resolution, t30_stats.image_x_resolution, t30_stats.image_y_resolution);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compression = %s (%d)\n", t4_encoding_to_str(t30_stats.encoding), t30_stats.encoding);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compressed image size = %d bytes\n", t30_stats.image_size);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad rows = %d\n", t30_stats.bad_rows);
@ -436,9 +449,11 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg)
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXPAGERESULT : SPANDSP_EVENT_RXFAXPAGERESULT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_image_resolution);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_line_image_resolution);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-file-image-resolution", fax_file_image_resolution);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-pixel-size", fax_image_pixel_size);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-pixel-size", fax_line_image_pixel_size);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-file-image-pixel-size", fax_file_image_pixel_size);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-bad-rows", fax_bad_rows);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-longest-bad-row-run", fax_longest_bad_row_run);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-encoding", fax_encoding);