From 2ed8e04776c34de9b17b6582979dc65e00c5f151 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sat, 31 Aug 2013 03:26:31 +0800 Subject: [PATCH] Tweaks to the spandsp alloc functions, and a fix for bi-level image row squashing. --- libs/spandsp/src/alloc.c | 68 ++++-- libs/spandsp/src/spandsp/alloc.h | 24 ++- libs/spandsp/src/spandsp/private/t4_rx.h | 13 +- libs/spandsp/src/spandsp/private/t4_tx.h | 14 +- libs/spandsp/src/spandsp/t42.h | 2 + libs/spandsp/src/spandsp/t85.h | 2 + libs/spandsp/src/t30.c | 18 +- libs/spandsp/src/t42.c | 34 ++- libs/spandsp/src/t43.c | 6 +- libs/spandsp/src/t4_rx.c | 258 ++++++++++++++++------- libs/spandsp/src/t4_tx.c | 203 ++++++++---------- libs/spandsp/src/t85_decode.c | 12 +- 12 files changed, 414 insertions(+), 240 deletions(-) diff --git a/libs/spandsp/src/alloc.c b/libs/spandsp/src/alloc.c index 06600adb30..b79aa166e7 100644 --- a/libs/spandsp/src/alloc.c +++ b/libs/spandsp/src/alloc.c @@ -50,21 +50,25 @@ #include "spandsp/telephony.h" #include "spandsp/alloc.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4232) /* address of dllimport is not static, identity not guaranteed */ #endif #if defined(HAVE_ALIGNED_ALLOC) static span_aligned_alloc_t __span_aligned_alloc = aligned_alloc; +static span_aligned_free_t __span_aligned_free = free; #elif defined(HAVE_MEMALIGN) static span_aligned_alloc_t __span_aligned_alloc = memalign; -#elif defined(HAVE_POSIX_MEMALIGN) -static void *fake_posix_memalign(size_t alignment, size_t size); -static span_aligned_alloc_t __span_aligned_alloc = fake_posix_memalign; +static span_aligned_free_t __span_aligned_free = free; +#elif defined(__MSVC__) +static void *fake_aligned_alloc(size_t alignment, size_t size); +static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc; +static span_aligned_free_t __span_aligned_free = _aligned_free; #else static void *fake_aligned_alloc(size_t alignment, size_t size); static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc; +static span_aligned_free_t __span_aligned_free = free; #endif static span_alloc_t __span_alloc = malloc; static span_realloc_t __span_realloc = realloc; @@ -76,12 +80,19 @@ static span_free_t __span_free = free; #if defined(HAVE_ALIGNED_ALLOC) #elif defined(HAVE_MEMALIGN) +#elif defined(__MSVC__) +static void *fake_aligned_alloc(size_t alignment, size_t size) +{ + /* Make Microsoft's _aligned_malloc() look like the C11 aligned_alloc */ + return _aligned_malloc(size, alignment); +} +/*- End of function --------------------------------------------------------*/ #elif defined(HAVE_POSIX_MEMALIGN) -static void *fake_posix_memalign(size_t alignment, size_t size) +static void *fake_aligned_alloc(size_t alignment, size_t size) { void *ptr; - /* Make posix_memalign look like the more modern aligned_alloc */ + /* Make posix_memalign() look like the C11 aligned_alloc */ posix_memalign(&ptr, alignment, size); return ptr; } @@ -94,12 +105,6 @@ static void *fake_aligned_alloc(size_t alignment, size_t size) /*- End of function --------------------------------------------------------*/ #endif -SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size) -{ - return __span_aligned_alloc(alignment, size); -} -/*- End of function --------------------------------------------------------*/ - SPAN_DECLARE(void *) span_alloc(size_t size) { return __span_alloc(size); @@ -118,11 +123,28 @@ SPAN_DECLARE(void) span_free(void *ptr) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, - span_alloc_t custom_alloc, - span_realloc_t custom_realloc, - span_free_t custom_free) +SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size) { + return __span_aligned_alloc(alignment, size); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(void) span_aligned_free(void *ptr) +{ + __span_aligned_free(ptr); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc, + span_realloc_t custom_realloc, + span_free_t custom_free, + span_aligned_alloc_t custom_aligned_alloc, + span_aligned_free_t custom_aligned_free) +{ + __span_alloc = (custom_alloc) ? custom_alloc : malloc; + __span_realloc = (custom_realloc) ? custom_realloc : realloc; + __span_free = (custom_free) ? custom_free : free; + __span_aligned_alloc = (custom_aligned_alloc) ? custom_aligned_alloc @@ -131,14 +153,18 @@ SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, aligned_alloc; #elif defined(HAVE_MEMALIGN) memalign; -#elif defined(HAVE_POSIX_MEMALIGN) - fake_posix_memalign; #else fake_aligned_alloc; #endif - __span_alloc = (custom_alloc) ? custom_alloc : malloc; - __span_realloc = (custom_realloc) ? custom_realloc : realloc; - __span_free = (custom_free) ? custom_free : free; + __span_aligned_free = (custom_aligned_free) + ? + custom_aligned_free + : +#if defined(__MSVC__) + _aligned_free; +#else + free; +#endif return 0; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/alloc.h b/libs/spandsp/src/spandsp/alloc.h index 6ad81aa9be..3bb691b05a 100644 --- a/libs/spandsp/src/spandsp/alloc.h +++ b/libs/spandsp/src/spandsp/alloc.h @@ -28,7 +28,17 @@ #if !defined(_SPANDSP_ALLOC_H_) #define _SPANDSP_ALLOC_H_ +/* Notes: + - Most platforms don't have an aligned realloc function, so we don't try to + support an aligned realloc on any platform. + - Some platforms use a special free function for memory which was allocated + by alligned allocation functions. We use a separate aligned_free function + on all platforms, for compatibility, even though it may simply reduce to + free(). + */ + typedef void *(*span_aligned_alloc_t)(size_t alignment, size_t size); +typedef void (*span_aligned_free_t)(void *ptr); typedef void *(*span_alloc_t)(size_t size); typedef void *(*span_realloc_t)(void *ptr, size_t size); typedef void (*span_free_t)(void *ptr); @@ -41,20 +51,24 @@ extern "C" /* Allocate size bytes allocated to ALIGNMENT bytes. */ SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size); +/* Free a block allocated by span_aligned_alloc, or span_aligned_realloc. */ +SPAN_DECLARE(void) span_aligned_free(void *ptr); + /* Allocate size bytes of memory. */ SPAN_DECLARE(void *) span_alloc(size_t size); /* Re-allocate the previously allocated block in ptr, making the new block size bytes long. */ SPAN_DECLARE(void *) span_realloc(void *ptr, size_t size); -/* Free a block allocated by span_alloc, span_aligned_alloc, or span_realloc. */ +/* Free a block allocated by span_alloc or span_realloc. */ SPAN_DECLARE(void) span_free(void *ptr); -SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, - span_alloc_t custom_alloc, +SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc, span_realloc_t custom_realloc, - span_free_t custom_free); - + span_free_t custom_free, + span_aligned_alloc_t custom_aligned_alloc, + span_aligned_free_t custom_aligned_free); + #if defined(__cplusplus) } #endif diff --git a/libs/spandsp/src/spandsp/private/t4_rx.h b/libs/spandsp/src/spandsp/private/t4_rx.h index 99a3e5ef55..ff2fc11567 100644 --- a/libs/spandsp/src/spandsp/private/t4_rx.h +++ b/libs/spandsp/src/spandsp/private/t4_rx.h @@ -91,6 +91,13 @@ typedef struct const char *dcs; } t4_rx_metadata_t; +typedef struct +{ + uint8_t *buf; + int buf_len; + int buf_ptr; +} no_decoder_state_t; + /*! T.4 FAX decompression descriptor. This defines the working state for a single instance of a T.4 FAX decompression channel. @@ -114,6 +121,7 @@ struct t4_rx_state_s union { + no_decoder_state_t no_decoder; t4_t6_decode_state_t t4_t6; t85_decode_state_t t85; #if defined(SPANDSP_SUPPORT_T88) @@ -132,11 +140,6 @@ struct t4_rx_state_s int current_decoder; - uint8_t *pre_encoded_buf; - int pre_encoded_len; - int pre_encoded_ptr; - int pre_encoded_bit; - /* Supporting information, like resolutions, which the backend may want. */ t4_rx_metadata_t metadata; diff --git a/libs/spandsp/src/spandsp/private/t4_tx.h b/libs/spandsp/src/spandsp/private/t4_tx.h index 5ff0d2ea27..d3c3e5a8a8 100644 --- a/libs/spandsp/src/spandsp/private/t4_tx.h +++ b/libs/spandsp/src/spandsp/private/t4_tx.h @@ -100,6 +100,14 @@ typedef struct int resolution_code; } t4_tx_metadata_t; +typedef struct +{ + uint8_t *buf; + int buf_len; + int buf_ptr; + int bit; +} no_encoder_state_t; + /*! T.4 FAX compression descriptor. This defines the working state for a single instance of a T.4 FAX compression channel. @@ -149,6 +157,7 @@ struct t4_tx_state_s union { + no_encoder_state_t no_encoder; t4_t6_encode_state_t t4_t6; t85_encode_state_t t85; #if defined(SPANDSP_SUPPORT_T88) @@ -176,10 +185,7 @@ struct t4_tx_state_s int pack_row; int pack_bit_mask; - uint8_t *pre_encoded_buf; - int pre_encoded_len; - int pre_encoded_ptr; - int pre_encoded_bit; + no_encoder_state_t no_encoder; /*! \brief Supporting information, like resolutions, which the backend may want. */ t4_tx_metadata_t metadata; diff --git a/libs/spandsp/src/spandsp/t42.h b/libs/spandsp/src/spandsp/t42.h index 17c4758a7f..26c4b8e299 100644 --- a/libs/spandsp/src/spandsp/t42.h +++ b/libs/spandsp/src/spandsp/t42.h @@ -76,6 +76,8 @@ SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, in SPAN_DECLARE(void) get_lab_gamut2(lab_params_t *s, int *L_P, int *L_Q, int *a_P, int *a_Q, int *b_P, int *b_Q); +SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len); + SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, uint32_t l0, int quality, int options); SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width); diff --git a/libs/spandsp/src/spandsp/t85.h b/libs/spandsp/src/spandsp/t85.h index d229026197..c6d6f0b47a 100644 --- a/libs/spandsp/src/spandsp/t85.h +++ b/libs/spandsp/src/spandsp/t85.h @@ -64,6 +64,8 @@ extern "C" { #endif +SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len); + /*! \brief Check if we are at the end of the current document page. \param s The T.85 context. \return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */ diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 110b5b2e5d..3a0d9bbc8b 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -1505,8 +1505,6 @@ static int build_dcs(t30_state_t *s) 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_NO_SUBSAMPLING)) - // set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1); use_bilevel = false; break; @@ -1789,17 +1787,13 @@ 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_200_400_CAPABLE)) { - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_400; - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_SUPERFINE; + s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_400; + s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_SUPERFINE; } if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE)) { - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_200; - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED)) - s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_FINE; + s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_200; + s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_FINE; s->mutual_colour_resolutions &= ~T4_RESOLUTION_200_200; } else @@ -6706,8 +6700,8 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s, | T4_SUPPORT_LENGTH_A4 | T4_SUPPORT_LENGTH_B4 | T4_SUPPORT_LENGTH_UNLIMITED; - /* Set the output encoding to something safe. For bi-level images ost things get - 1D and 2D encoding right. Quite a lot get other things wrong. */ + /* Set the output encoding to something safe. For bi-level images most things + get 1D and 2D encoding right. Quite a lot get other things wrong. */ s->supported_output_compressions = T4_COMPRESSION_T4_2D | T4_COMPRESSION_JPEG; s->local_min_scan_time_code = T30_MIN_SCAN_0MS; span_log_init(&s->logging, SPAN_LOG_NONE, NULL); diff --git a/libs/spandsp/src/t42.c b/libs/spandsp/src/t42.c index 1469c389be..37c98e1d95 100644 --- a/libs/spandsp/src/t42.c +++ b/libs/spandsp/src/t42.c @@ -72,7 +72,7 @@ #include "spandsp/private/t85.h" #include "spandsp/private/t42.h" -/* The open_memstream() and fmemopen() in older versions of glibc seems quirky */ +/* The open_memstream() and fmemopen() in older versions of glibc seem quirky */ #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 12)) #undef OPEN_MEMSTREAM #endif @@ -230,6 +230,38 @@ static __inline__ int unpack_16(uint8_t *s, uint16_t value) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len) +{ + int type; + int seg; + int pos; + + /* Search the image data for its width and length */ + *length = 0; + *width = 0; + + pos = 0; + if (pack_16(&data[pos]) != 0xFFD8) + return false; + pos += 2; + while (pos < len) + { + type = pack_16(&data[pos]); + pos += 2; + seg = pack_16(&data[pos]) - 2; + pos += 2; + if (type == 0xFFC0) + { + *length = pack_16(&data[pos + 1]); + *width = pack_16(&data[pos + 3]); + return true; + } + pos += seg; + } + return false; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) xyz_to_corrected_color_temp(float *temp, float xyz[3]) { float us; diff --git a/libs/spandsp/src/t43.c b/libs/spandsp/src/t43.c index 181226e757..ec7e67ea3a 100644 --- a/libs/spandsp/src/t43.c +++ b/libs/spandsp/src/t43.c @@ -865,7 +865,8 @@ SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s) { /* ITULAB */ /* Illuminant D50 */ - set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f); set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false); s->t85.min_bit_planes = 1; @@ -898,7 +899,8 @@ SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s, /* ITULAB */ /* Illuminant D50 */ - set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); + set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f); set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false); s->t85.min_bit_planes = 1; diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index 141a6529e9..4723b0111c 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -213,6 +213,8 @@ static int set_tiff_directory_info(t4_rx_state_t *s) int bits_per_sample; int samples_per_pixel; int photometric; + uint32_t width; + uint32_t length; t = &s->tiff; /* Prepare the directory entry fully before writing the image, or libtiff complains */ @@ -274,8 +276,16 @@ static int set_tiff_directory_info(t4_rx_state_t *s) case T4_COMPRESSION_SYCC_T81: output_compression = COMPRESSION_JPEG; bits_per_sample = 8; - samples_per_pixel = 3; - photometric = PHOTOMETRIC_YCBCR; + if (t->image_type == T4_IMAGE_TYPE_COLOUR_8BIT) + { + samples_per_pixel = 3; + photometric = PHOTOMETRIC_YCBCR; + } + else + { + samples_per_pixel = 1; + photometric = PHOTOMETRIC_MINISBLACK; + } break; #endif #if defined(SPANDSP_SUPPORT_T43) @@ -399,7 +409,21 @@ static int set_tiff_directory_info(t4_rx_state_t *s) switch (s->current_decoder) { case 0: - s->metadata.image_length = 1024; + switch (t->compression) + { + case T4_COMPRESSION_T42_T81: + case T4_COMPRESSION_SYCC_T81: + t42_analyse_header(&width, &length, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr); + s->metadata.image_width = width; + s->metadata.image_length = length; + break; + case T4_COMPRESSION_T85: + case T4_COMPRESSION_T85_L0: + t85_analyse_header(&width, &length, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr); + s->metadata.image_width = width; + s->metadata.image_length = length; + break; + } 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))) @@ -607,7 +631,7 @@ static int write_tiff_image(t4_rx_state_t *s) #endif t = &s->tiff; - if (s->pre_encoded_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0)) + if (s->decoder.no_decoder.buf_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0)) return -1; /* Set up the TIFF directory info... */ set_tiff_directory_info(s); @@ -616,9 +640,9 @@ static int write_tiff_image(t4_rx_state_t *s) //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... */ - if (s->pre_encoded_ptr > 0) + if (s->current_decoder == 0) { - if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->pre_encoded_buf, s->pre_encoded_ptr) < 0) + if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr) < 0) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file); } else @@ -752,30 +776,57 @@ SPAN_DECLARE(int) t4_rx_put_bit(t4_rx_state_t *s, int bit) } /*- End of function --------------------------------------------------------*/ +static void pre_encoded_restart(no_decoder_state_t *s) +{ + s->buf_ptr = 0; +} +/*- End of function --------------------------------------------------------*/ + +static void pre_encoded_init(no_decoder_state_t *s) +{ + s->buf = NULL; + s->buf_len = 0; + s->buf_ptr = 0; +} +/*- End of function --------------------------------------------------------*/ + +static int pre_encoded_release(no_decoder_state_t *s) +{ + if (s->buf) + span_free(s->buf); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static int pre_encoded_put(no_decoder_state_t *s, const uint8_t data[], size_t len) +{ + uint8_t *buf; + + if (s->buf_len < s->buf_ptr + len) + { + s->buf_len += 65536; + if ((buf = span_realloc(s->buf, s->buf_len)) == NULL) + { + if (s->buf) + { + span_free(s->buf); + s->buf = NULL; + s->buf_len = 0; + } + return -1; + } + s->buf = buf; + } + memcpy(&s->buf[s->buf_ptr], data, len); + s->buf_ptr += len; + return T4_DECODE_MORE_DATA; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len) { - uint8_t *buf2; - s->line_image_size += 8*len; - if (s->pre_encoded_len > 0) - { - if (s->pre_encoded_len < s->pre_encoded_ptr + 65536) - { - s->pre_encoded_len += 65536; - if ((buf2 = span_realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL) - { - if (s->pre_encoded_buf) - span_free(s->pre_encoded_buf); - return -1; - } - s->pre_encoded_buf = buf2; - } - memcpy(&s->pre_encoded_buf[s->pre_encoded_ptr], buf, len); - s->pre_encoded_ptr += len; - return T4_DECODE_MORE_DATA; - } - if (s->image_put_handler) return s->image_put_handler((void *) &s->decoder, buf, len); @@ -825,13 +876,23 @@ SPAN_DECLARE(void) t4_rx_set_model(t4_rx_state_t *s, const char *model) } /*- End of function --------------------------------------------------------*/ -static void select_tiff_compression(t4_rx_state_t *s, int output_image_type) +static bool select_tiff_compression(t4_rx_state_t *s, int output_image_type) { + s->tiff.image_type = output_image_type; + if ((s->metadata.compression & (s->supported_tiff_compressions & (T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0 | T4_COMPRESSION_T42_T81 | T4_COMPRESSION_SYCC_T81)))) + { + span_log(&s->logging, SPAN_LOG_FLOW, "Image can be written without recoding\n"); + s->tiff.compression = s->metadata.compression; + return false; + } + if (output_image_type == T4_IMAGE_TYPE_BILEVEL) { /* Only provide for one form of coding throughout the file, even though the coding on the wire could change between pages. */ - if ((s->supported_tiff_compressions & T4_COMPRESSION_T85)) + if ((s->supported_tiff_compressions & T4_COMPRESSION_T88)) + s->tiff.compression = T4_COMPRESSION_T88; + else if ((s->supported_tiff_compressions & T4_COMPRESSION_T85)) s->tiff.compression = T4_COMPRESSION_T85; else if ((s->supported_tiff_compressions & T4_COMPRESSION_T6)) s->tiff.compression = T4_COMPRESSION_T6; @@ -848,22 +909,46 @@ static void select_tiff_compression(t4_rx_state_t *s, int output_image_type) s->tiff.compression = T4_COMPRESSION_T42_T81; else if ((s->supported_tiff_compressions & T4_COMPRESSION_T43)) s->tiff.compression = T4_COMPRESSION_T43; + else if ((s->supported_tiff_compressions & T4_COMPRESSION_T45)) + s->tiff.compression = T4_COMPRESSION_T45; else if ((s->supported_tiff_compressions & T4_COMPRESSION_UNCOMPRESSED)) s->tiff.compression = T4_COMPRESSION_UNCOMPRESSED; } - s->tiff.image_type = output_image_type; + return true; +} +/*- End of function --------------------------------------------------------*/ + +static int release_current_decoder(t4_rx_state_t *s) +{ + switch (s->current_decoder) + { + case 0: + return pre_encoded_release(&s->decoder.no_decoder); + 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 | T4_COMPRESSION_T85_L0: + return t85_decode_release(&s->decoder.t85); +#if defined(SPANDSP_SUPPORT_T88) + case T4_COMPRESSION_T88: + return t88_decode_release(&s->decoder.t88); +#endif + 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 +#if defined(SPANDSP_SUPPORT_T45) + case T4_COMPRESSION_T45: + return t45_decode_release(&s->decoder.t45); +#endif + } + return 0; } /*- 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: @@ -876,12 +961,18 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T6: break; default: + release_current_decoder(s); 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; - select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return t4_t6_decode_set_encoding(&s->decoder.t4_t6, compression); case T4_COMPRESSION_T85: case T4_COMPRESSION_T85_L0: @@ -891,6 +982,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T85_L0: break; default: + release_current_decoder(s); 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 @@ -900,7 +992,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #if defined(SPANDSP_SUPPORT_T88) case T4_COMPRESSION_T88: @@ -909,12 +1006,18 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T88: break; default: + release_current_decoder(s); t88_decode_init(&s->decoder.t88, s->row_handler, s->row_handler_user_data); s->current_decoder = T4_COMPRESSION_T88; break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #endif case T4_COMPRESSION_T42_T81: @@ -925,6 +1028,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_SYCC_T81: break; default: + release_current_decoder(s); 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 @@ -934,7 +1038,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: @@ -943,6 +1052,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T43: break; default: + release_current_decoder(s); 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 @@ -952,7 +1062,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) break; } s->metadata.compression = compression; - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #endif #if defined(SPANDSP_SUPPORT_T45) @@ -962,18 +1077,23 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression) case T4_COMPRESSION_T45: break; default: + release_current_decoder(s); 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; - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT)) + { + release_current_decoder(s); + s->current_decoder = 0; + pre_encoded_init(&s->decoder.no_decoder); + } return 0; #endif } return -1; -#endif } /*- End of function --------------------------------------------------------*/ @@ -1026,6 +1146,15 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t t->compression = s->metadata.compression; switch (s->current_decoder) { + case 0: + t->type = 0; + t->width = s->metadata.image_width; + t->length = s->metadata.image_length; + t->image_type = 0; + t->image_width = t->width; + t->image_length = t->length; + t->line_image_size = s->line_image_size; + break; 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); @@ -1085,9 +1214,8 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s) switch (s->current_decoder) { case 0: - s->pre_encoded_ptr = 0; - s->pre_encoded_len = 0; - s->image_put_handler = NULL; + pre_encoded_restart(&s->decoder.no_decoder); + s->image_put_handler = (t4_image_put_handler_t) pre_encoded_put; break; case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6: t4_t6_decode_restart(&s->decoder.t4_t6, s->metadata.image_width); @@ -1163,7 +1291,7 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s) switch (s->current_decoder) { case 0: - length = s->pre_encoded_ptr; + length = s->decoder.no_decoder.buf_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); @@ -1179,9 +1307,9 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s) case T4_COMPRESSION_T42_T81: length = t42_decode_get_image_length(&s->decoder.t42); if (s->decoder.t42.samples_per_pixel == 3) - select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT); + s->tiff.image_type = T4_IMAGE_TYPE_COLOUR_8BIT; else - select_tiff_compression(s, T4_IMAGE_TYPE_GRAY_8BIT); + s->tiff.image_type = T4_IMAGE_TYPE_GRAY_8BIT; break; #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: @@ -1203,7 +1331,6 @@ 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 { @@ -1240,6 +1367,15 @@ SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int span_log(&s->logging, SPAN_LOG_FLOW, "Start rx document\n"); s->supported_tiff_compressions = supported_output_compressions; +#if !defined(SPANDSP_SUPPORT_T88) + s->supported_tiff_compressions &= ~T4_COMPRESSION_T88; +#endif +#if !defined(SPANDSP_SUPPORT_T43) + s->supported_tiff_compressions &= ~T4_COMPRESSION_T43; +#endif +#if !defined(SPANDSP_SUPPORT_T45) + s->supported_tiff_compressions &= ~T4_COMPRESSION_T45; +#endif /* Set some default values */ s->metadata.x_resolution = T4_X_RESOLUTION_R8; @@ -1272,27 +1408,7 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s) { if (s->tiff.file) tiff_rx_release(s); - switch (s->current_decoder) - { - 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 | T4_COMPRESSION_T85_L0: - return t85_decode_release(&s->decoder.t85); -#if defined(SPANDSP_SUPPORT_T88) - case T4_COMPRESSION_T88: - return t88_decode_release(&s->decoder.t88); -#endif - 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 -#if defined(SPANDSP_SUPPORT_T45) - case T4_COMPRESSION_T45: - return t45_decode_release(&s->decoder.t45); -#endif - } + release_current_decoder(s); return -1; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 0c17b585f2..f38239f492 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -873,20 +873,20 @@ static int read_tiff_raw_image(t4_tx_state_t *s) total_len = 0; for (i = 0; i < num_strips; i++) total_len += TIFFRawStripSize(s->tiff.tiff_file, i); - if ((s->pre_encoded_buf = span_realloc(s->pre_encoded_buf, total_len)) == NULL) + if ((s->no_encoder.buf = span_realloc(s->no_encoder.buf, total_len)) == NULL) return -1; total_len = 0; for (i = 0; i < num_strips; i++, total_len += len) { len = TIFFRawStripSize(s->tiff.tiff_file, i); - if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &s->pre_encoded_buf[total_len], len)) < 0) + if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &s->no_encoder.buf[total_len], len)) < 0) { span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadRawStrip error.\n", s->tiff.file); return -1; } } - s->pre_encoded_len = total_len; - s->pre_encoded_ptr = 0; + s->no_encoder.buf_len = total_len; + s->no_encoder.buf_ptr = 0; return 0; } /*- End of function --------------------------------------------------------*/ @@ -1674,7 +1674,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, int width_code; int res_code; /* Correct resolution code */ int alt_res_code; /* Fallback resolution code, where a metric/inch swap is possible */ - } width_info[] = + } width_and_res_info[] = { { T4_WIDTH_100_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_100_100, 0}, { T4_WIDTH_100_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_100_100, 0}, @@ -1777,7 +1777,9 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, int entry; int compression; int res; + int supported_colour_compressions; + supported_colour_compressions = supported_compressions & (T4_COMPRESSION_T42_T81 | T4_COMPRESSION_T43 | T4_COMPRESSION_T45 | T4_COMPRESSION_SYCC_T81); compression = -1; s->metadata.image_type = s->tiff.image_type; if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL) @@ -1786,7 +1788,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, /* Can we send this page as it is? */ if (supported_colour_resolutions && - (supported_compressions & (T4_COMPRESSION_T42_T81 | T4_COMPRESSION_T43 | T4_COMPRESSION_T45 | T4_COMPRESSION_SYCC_T81)) + supported_colour_compressions && (((s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT) && @@ -1798,28 +1800,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, { /* Gray-scale/colour is possible */ span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is allowed\n"); - if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT) - { - if (!(supported_compressions & T4_COMPRESSION_COLOUR)) - { - span_log(&s->logging, SPAN_LOG_FLOW, "Colour is not allowed\n"); - return T4_IMAGE_FORMAT_INCOMPATIBLE; - } - } - else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT) - { - if (!(supported_compressions & T4_COMPRESSION_GRAYSCALE)) - { - span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale is not allowed\n"); - return T4_IMAGE_FORMAT_INCOMPATIBLE; - } - } /* Choose the best gray-scale/colour encoding available to us */ if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL && (supported_compressions & T4_COMPRESSION_T43)) compression = T4_COMPRESSION_T43; @@ -1838,32 +1818,29 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, { /* Gray-scale/colour is not possible. Can we flatten the image to send it? */ span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is not allowed\n"); - if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT) + switch (s->tiff.image_type) { + case T4_IMAGE_TYPE_COLOUR_BILEVEL: + case T4_IMAGE_TYPE_COLOUR_8BIT: + case T4_IMAGE_TYPE_COLOUR_12BIT: if (!(supported_compressions & T4_COMPRESSION_COLOUR_TO_BILEVEL)) { span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n"); return T4_IMAGE_FORMAT_INCOMPATIBLE; } - s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL; - } - else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT - || - s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT) - { + break; + case T4_IMAGE_TYPE_GRAY_8BIT: + case T4_IMAGE_TYPE_GRAY_12BIT: if (!(supported_compressions & T4_COMPRESSION_GRAY_TO_BILEVEL)) { span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n"); return T4_IMAGE_FORMAT_INCOMPATIBLE; } - s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL; + break; } /* Squashing to a bi-level image is possible */ - span_log(&s->logging, SPAN_LOG_FLOW, "The image may be flattened to %d\n", s->metadata.image_type); + s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL; + span_log(&s->logging, SPAN_LOG_FLOW, "The image will be flattened to %d\n", s->metadata.image_type); } } @@ -1884,26 +1861,20 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, /* Deal with the image width/resolution combination. */ /* Look for a pattern that matches the image */ - res = T4_IMAGE_FORMAT_NOSIZESUPPORT; - for (entry = 0; s->tiff.image_width >= width_info[entry].width; entry++) + s->metadata.width_code = -1; + for (entry = 0; s->tiff.image_width >= width_and_res_info[entry].width; entry++) { - if (s->tiff.image_width == width_info[entry].width && s->tiff.resolution_code == width_info[entry].res_code) + if (s->tiff.image_width == width_and_res_info[entry].width && s->tiff.resolution_code == width_and_res_info[entry].res_code) { - res = T4_IMAGE_FORMAT_OK; + s->metadata.width_code = width_and_res_info[entry].width_code; break; } } - - s->metadata.width_code = width_info[entry].width_code; - + res = T4_IMAGE_FORMAT_NOSIZESUPPORT; s->row_squashing_ratio = 1; - if (res == T4_IMAGE_FORMAT_OK) + if (s->metadata.width_code >= 0 && (supported_image_sizes & s->metadata.width_code)) { - /* We have a valid width/resolution combination */ - - /* Check if this width/resolution combination is supported */ - if (!(supported_image_sizes & width_info[entry].width_code)) - return T4_IMAGE_FORMAT_NOSIZESUPPORT; + /* We have a valid and supported width/resolution combination */ /* No resize necessary */ s->metadata.image_width = s->tiff.image_width; @@ -1912,7 +1883,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, res = T4_IMAGE_FORMAT_NORESSUPPORT; if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL) { - if ((width_info[entry].res_code & supported_bilevel_resolutions)) + if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions)) { /* We can use the resolution of the original image */ s->metadata.resolution_code = s->tiff.resolution_code; @@ -1920,56 +1891,51 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); res = T4_IMAGE_FORMAT_OK; } + else if ((width_and_res_info[entry].alt_res_code & supported_bilevel_resolutions)) + { + /* We can do a metric/imperial swap, and have a usable resolution */ + span_log(&s->logging, + SPAN_LOG_FLOW, + "Image resolution %s falls back to %s\n", + t4_image_resolution_to_str(s->tiff.resolution_code), + t4_image_resolution_to_str(width_and_res_info[entry].alt_res_code)); + s->metadata.resolution_code = width_and_res_info[entry].alt_res_code; + s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); + s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); + res = T4_IMAGE_FORMAT_OK; + } else { - /* The resolution is not supported, but there might be an approximation, or a length - squashing that might work. */ - if ((width_info[entry].alt_res_code & supported_bilevel_resolutions)) + if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) { - /* We can do a metric/imperial swap, and have a usable resolution */ - span_log(&s->logging, - SPAN_LOG_FLOW, - "Image resolution %s falls back to %s\n", - t4_image_resolution_to_str(s->tiff.resolution_code), - t4_image_resolution_to_str(width_info[entry].alt_res_code)); - s->metadata.resolution_code = width_info[entry].alt_res_code; - s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); - s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); - res = T4_IMAGE_FORMAT_OK; - } - else - { - if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) + if ((s->tiff.resolution_code & (T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE))) { - if ((s->tiff.resolution_code & (T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE))) + /* This might be a resolution we can squash down to something which is supported */ + for (i = 0; i < 4; i++) { - /* This might be a resolution we can squash down to something which is supported */ - for (i = 0; i < 4; i++) + if ((s->tiff.resolution_code & squashable[i].resolution)) + break; + } + if (i < 4) + { + /* This is a squashable resolution, so let's see if there is a valid + fallback we can squash the image to, scanning through the entries + in their order of preference. */ + for (j = 0; j < 4; j++) { - if ((s->tiff.resolution_code & squashable[i].resolution)) - break; - } - if (i < 4) - { - /* This is a squashable resolution, so let's see if there is a valid - fallback we can squash the image to, scanning through the entries - in their order of preference. */ - for (j = 0; j < 4; j++) + if ((supported_bilevel_resolutions & squashable[i].fallback[j].resolution)) { - if ((supported_bilevel_resolutions & squashable[i].fallback[j].resolution)) - { - span_log(&s->logging, - SPAN_LOG_FLOW, - "Image resolution %s falls back to %s\n", - t4_image_resolution_to_str(s->tiff.resolution_code), - t4_image_resolution_to_str(squashable[i].fallback[j].resolution)); - s->row_squashing_ratio = squashable[i].fallback[j].squashing_factor; - s->metadata.resolution_code = squashable[i].fallback[j].resolution; - s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); - s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); - res = T4_IMAGE_FORMAT_OK; - break; - } + span_log(&s->logging, + SPAN_LOG_FLOW, + "Image resolution %s falls back to %s\n", + t4_image_resolution_to_str(s->tiff.resolution_code), + t4_image_resolution_to_str(squashable[i].fallback[j].resolution)); + s->row_squashing_ratio = squashable[i].fallback[j].squashing_factor; + s->metadata.resolution_code = squashable[i].fallback[j].resolution; + s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); + s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); + res = T4_IMAGE_FORMAT_OK; + break; } } } @@ -1977,25 +1943,25 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, } } /* If we have not succeeded in matching up the size and resolution, the next step will - depend on whether the original was a bi-level image. If it was we are stuck, as you can't + depend on whether the original was a bi-level image. If it was, we are stuck, as you can't really resize those. If it was not, a resize might be possible */ if (res != T4_IMAGE_FORMAT_OK) { if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) return T4_IMAGE_FORMAT_NORESSUPPORT; if (!(supported_compressions & T4_COMPRESSION_RESCALING)) - return T4_IMAGE_FORMAT_NORESSUPPORT; + return T4_IMAGE_FORMAT_NOSIZESUPPORT; } /* TODO */ } else { - if ((width_info[entry].res_code & supported_bilevel_resolutions)) + if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions)) { if ((s->tiff.resolution_code & supported_colour_resolutions)) { /* We can use the resolution of the original image */ - s->metadata.resolution_code = width_info[entry].res_code; + s->metadata.resolution_code = width_and_res_info[entry].res_code; s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code); res = T4_IMAGE_FORMAT_OK; @@ -2007,12 +1973,13 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s, { /* Can we rework the image to fit? */ /* We can't rework a bilevel image that fits none of the patterns */ - if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL) + if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL) return T4_IMAGE_FORMAT_NORESSUPPORT; if (!(supported_compressions & T4_COMPRESSION_RESCALING)) - return T4_IMAGE_FORMAT_NORESSUPPORT; - res = T4_IMAGE_FORMAT_OK; + return T4_IMAGE_FORMAT_NOSIZESUPPORT; /* Any other kind of image might be resizable */ + res = T4_IMAGE_FORMAT_OK; + /* TODO: use more sophisticated resizing */ s->metadata.image_width = T4_WIDTH_200_A4; s->metadata.resolution_code = T4_RESOLUTION_200_200; s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code); @@ -2430,9 +2397,9 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s) { - if (s->pre_encoded_len > 0) + if (s->no_encoder.buf_len > 0) { - if (s->pre_encoded_ptr >= s->pre_encoded_len) + if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len) return SIG_STATUS_END_OF_DATA; return 0; } @@ -2471,15 +2438,15 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s) int bit; /* We only get bit by bit for T.4 1D and T.4 2-D. */ - if (s->pre_encoded_len > 0) + if (s->no_encoder.buf_len > 0) { - if (s->pre_encoded_ptr >= s->pre_encoded_len) + if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len) return SIG_STATUS_END_OF_DATA; - bit = (s->pre_encoded_buf[s->pre_encoded_ptr] >> s->pre_encoded_bit) & 1; - if (++s->pre_encoded_bit >= 8) + bit = (s->no_encoder.buf[s->no_encoder.buf_ptr] >> s->no_encoder.bit) & 1; + if (++s->no_encoder.bit >= 8) { - s->pre_encoded_bit = 0; - s->pre_encoded_ptr++; + s->no_encoder.bit = 0; + s->no_encoder.buf_ptr++; } return bit; } @@ -2489,12 +2456,12 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s) SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len) { - if (s->pre_encoded_len > 0) + if (s->no_encoder.buf_len > 0) { - if (max_len > (s->pre_encoded_len - s->pre_encoded_ptr)) - max_len = s->pre_encoded_len - s->pre_encoded_ptr; - memcpy(buf, &s->pre_encoded_buf[s->pre_encoded_ptr], max_len); - s->pre_encoded_ptr += max_len; + if (max_len > (s->no_encoder.buf_len - s->no_encoder.buf_ptr)) + max_len = s->no_encoder.buf_len - s->no_encoder.buf_ptr; + memcpy(buf, &s->no_encoder.buf[s->no_encoder.buf_ptr], max_len); + s->no_encoder.buf_ptr += max_len; return max_len; } diff --git a/libs/spandsp/src/t85_decode.c b/libs/spandsp/src/t85_decode.c index 8af029d3a0..d7d1210367 100644 --- a/libs/spandsp/src/t85_decode.c +++ b/libs/spandsp/src/t85_decode.c @@ -53,7 +53,7 @@ #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -static __inline__ int32_t pack_32(uint8_t *s) +static __inline__ int32_t pack_32(const uint8_t *s) { int32_t value; @@ -265,6 +265,16 @@ static int finish_sde(t85_decode_state_t *s) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len) +{ + if (len < 20) + return false; + *width = pack_32(&data[6]); + *length = pack_32(&data[10]); + return true; +} +/*- End of function --------------------------------------------------------*/ + static int check_bih(t85_decode_state_t *s) { /* Check that the fixed parameters have the values they are expected to be