]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Tweaks to the spandsp alloc functions, and a fix for bi-level image row
authorSteve Underwood <steveu@haswell.coppice.org>
Fri, 30 Aug 2013 19:26:31 +0000 (03:26 +0800)
committerSteve Underwood <steveu@haswell.coppice.org>
Fri, 30 Aug 2013 19:26:31 +0000 (03:26 +0800)
squashing.

12 files changed:
libs/spandsp/src/alloc.c
libs/spandsp/src/spandsp/alloc.h
libs/spandsp/src/spandsp/private/t4_rx.h
libs/spandsp/src/spandsp/private/t4_tx.h
libs/spandsp/src/spandsp/t42.h
libs/spandsp/src/spandsp/t85.h
libs/spandsp/src/t30.c
libs/spandsp/src/t42.c
libs/spandsp/src/t43.c
libs/spandsp/src/t4_rx.c
libs/spandsp/src/t4_tx.c
libs/spandsp/src/t85_decode.c

index 06600adb309dccb3e9c2fdf75fae165d0594e168..b79aa166e7c109d5b70cba2d640aa444cc05b25e 100644 (file)
 #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_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_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 --------------------------------------------------------*/
index 6ad81aa9be509f0c36082c52c507526399b16335..3bb691b05a194fab06706989217d91b16c596511 100644 (file)
 #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
index 99a3e5ef55167e1d27a2959c38d1b2b1ff447e25..ff2fc1156762dcb3c779b8a7b1d083530397611e 100644 (file)
@@ -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;
 
index 5ff0d2ea272cadbd70c6c2d331d84f68cf165359..d3c3e5a8a89cb7876d05be61fba89e03f06fa7c9 100644 (file)
@@ -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;
index 17c4758a7fb0abdd1b5219121905f8631f19c9b0..26c4b8e299f0fcab3109bcbc4f0c389365616fd2 100644 (file)
@@ -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);
index d229026197a4b2399fd3ab30b596c792d03497ae..c6d6f0b47add3ea46b2a8411643a235f2011945a 100644 (file)
@@ -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. */
index 110b5b2e5dd819c4b93b3ae0d4bb0f6e7339de27..3a0d9bbc8b6a8fa67be34870ab01a03d6e3d5d1d 100644 (file)
@@ -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);
index 1469c389bef61f8e16824fa175d9da1d0560f050..37c98e1d95ddbdadbfadd3ef2094f4c09a482a1d 100644 (file)
@@ -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;
index 181226e75790a3de6b9538ad6ccf27f3f16c5d25..ec7e67ea3a9bf8896c3f0b51599a38c78925c0cb 100644 (file)
@@ -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;
index 141a6529e9eaf1319299d33610733b22471b856b..4723b0111c0a39c185ad5d4ab33ef50ee68cb853 100644 (file)
@@ -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,29 +776,56 @@ SPAN_DECLARE(int) t4_rx_put_bit(t4_rx_state_t *s, int bit)
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len)
+static void pre_encoded_restart(no_decoder_state_t *s)
 {
-    uint8_t *buf2;
+    s->buf_ptr = 0;
+}
+/*- End of function --------------------------------------------------------*/
 
-    s->line_image_size += 8*len;
+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->pre_encoded_len > 0)
+    if (s->buf_len < s->buf_ptr + len)
     {
-        if (s->pre_encoded_len < s->pre_encoded_ptr + 65536)
+        s->buf_len += 65536;
+        if ((buf = span_realloc(s->buf, s->buf_len)) == NULL)
         {
-            s->pre_encoded_len += 65536;
-            if ((buf2 = span_realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL)
+            if (s->buf)
             {
-                if (s->pre_encoded_buf)
-                    span_free(s->pre_encoded_buf);
-                return -1;
+                span_free(s->buf);
+                s->buf = NULL;
+                s->buf_len = 0;
             }
-            s->pre_encoded_buf = buf2;
+            return -1;
         }
-        memcpy(&s->pre_encoded_buf[s->pre_encoded_ptr], buf, len);
-        s->pre_encoded_ptr += len;
-        return T4_DECODE_MORE_DATA;
+        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)
+{
+    s->line_image_size += 8*len;
 
     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 --------------------------------------------------------*/
 
-SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
+static int release_current_decoder(t4_rx_state_t *s)
 {
-#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;
+    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;
-#else
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
+{
     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 --------------------------------------------------------*/
index 0c17b585f23e4a986c47dab2504704629938808b..f38239f4928d1d53ae14c731e18ce256a18cd276 100644 (file)
@@ -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))
-                {
-                    /* 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.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)
+                            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++)
                             {
-                                /* 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;
     }
 
index 8af029d3a0374a28075669d99237c3215c5c4676..d7d1210367cb76e153e26b28922cdd2e2adbe464 100644 (file)
@@ -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