]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
More movement towards colour FAXing
authorSteve Underwood <steveu@coppice.org>
Sun, 21 Apr 2013 14:02:09 +0000 (22:02 +0800)
committerSteve Underwood <steveu@coppice.org>
Sun, 21 Apr 2013 14:02:09 +0000 (22:02 +0800)
27 files changed:
libs/spandsp/configure.ac
libs/spandsp/src/Makefile.am
libs/spandsp/src/fax_modems.c
libs/spandsp/src/spandsp.h.in
libs/spandsp/src/spandsp/private/fax_modems.h
libs/spandsp/src/spandsp/private/t30.h
libs/spandsp/src/spandsp/private/t30_dis_dtc_dcs_bits.h
libs/spandsp/src/spandsp/private/t38_gateway.h
libs/spandsp/src/spandsp/private/t43.h [new file with mode: 0644]
libs/spandsp/src/spandsp/private/t4_rx.h
libs/spandsp/src/spandsp/private/t4_tx.h
libs/spandsp/src/spandsp/private/v18.h
libs/spandsp/src/spandsp/t30_api.h
libs/spandsp/src/spandsp/t43.h [new file with mode: 0644]
libs/spandsp/src/spandsp/t4_rx.h
libs/spandsp/src/t30.c
libs/spandsp/src/t30_api.c
libs/spandsp/src/t43.c [new file with mode: 0644]
libs/spandsp/src/t4_rx.c
libs/spandsp/src/t4_tx.c
libs/spandsp/src/v17rx.c
libs/spandsp/tests/fax_tests.c
libs/spandsp/tests/t31_tests.c
libs/spandsp/tests/t38_decode.c
libs/spandsp/tests/t42_tests.c
libs/spandsp/tests/tsb85_tests.c
src/mod/applications/mod_spandsp/mod_spandsp_fax.c

index ad379aecbead903c4c7231f9d69387f8d4e094e8..63bca1dd7fd6f81e78ad9926d06aee6aabb83a64 100644 (file)
@@ -261,6 +261,8 @@ fi
 SPANDSP_SUPPORT_T42="#undef SPANDSP_SUPPORT_T42"
 #AC_DEFINE([SPANDSP_SUPPORT_T43], [1], [Support T.43 JBIG gray and colour compression])
 SPANDSP_SUPPORT_T43="#undef SPANDSP_SUPPORT_T43"
+#AC_DEFINE([SPANDSP_SUPPORT_V32BIS], [1], [Support the V.32bis modem])
+SPANDSP_SUPPORT_V32BIS="#undef SPANDSP_SUPPORT_V32BIS"
 #AC_DEFINE([SPANDSP_SUPPORT_V34], [1], [Support the V.34 FAX modem])
 SPANDSP_SUPPORT_V34="#undef SPANDSP_SUPPORT_V34"
 
@@ -567,6 +569,7 @@ AC_SUBST(SPANDSP_MISALIGNED_ACCESS_FAILS)
 AC_SUBST(SPANDSP_USE_EXPORT_CAPABILITY)
 AC_SUBST(SPANDSP_SUPPORT_T42)
 AC_SUBST(SPANDSP_SUPPORT_T43)
+AC_SUBST(SPANDSP_SUPPORT_V32BIS)
 AC_SUBST(SPANDSP_SUPPORT_V34)
 AC_SUBST(SPANDSP_SUPPORT_TIFF_FX)
 AC_SUBST(INSERT_INTTYPES_HEADER)
index 2bab4a9a563b68caee38106a8a5fc6d1d04e829a..368f4573116aa5970453f18b443e1d571b5c023a 100644 (file)
@@ -22,28 +22,17 @@ AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
 DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \
                  $(srcdir)/cielab_luts.h \
                  $(srcdir)/math_fixed_tables.h \
-                 $(srcdir)/v17_v32bis_rx_fixed_rrc.h \
-                 $(srcdir)/v17_v32bis_rx_floating_rrc.h \
-                 $(srcdir)/v17_v32bis_tx_fixed_rrc.h \
-                 $(srcdir)/v17_v32bis_tx_floating_rrc.h \
-                 $(srcdir)/v22bis_rx_1200_fixed_rrc.h \
-                 $(srcdir)/v22bis_rx_2400_fixed_rrc.h \
-                 $(srcdir)/v22bis_rx_1200_floating_rrc.h \
-                 $(srcdir)/v22bis_rx_2400_floating_rrc.h \
-                 $(srcdir)/v22bis_tx_fixed_rrc.h \
-                 $(srcdir)/v22bis_tx_floating_rrc.h \
-                 $(srcdir)/v27ter_rx_2400_fixed_rrc.h \
-                 $(srcdir)/v27ter_rx_4800_fixed_rrc.h \
-                 $(srcdir)/v27ter_rx_2400_floating_rrc.h \
-                 $(srcdir)/v27ter_rx_4800_floating_rrc.h \
-                 $(srcdir)/v27ter_tx_2400_fixed_rrc.h \
-                 $(srcdir)/v27ter_tx_4800_fixed_rrc.h \
-                 $(srcdir)/v27ter_tx_2400_floating_rrc.h \
-                 $(srcdir)/v27ter_tx_4800_floating_rrc.h \
-                 $(srcdir)/v29rx_fixed_rrc.h \
-                 $(srcdir)/v29rx_floating_rrc.h \
-                 $(srcdir)/v29tx_fixed_rrc.h \
-                 $(srcdir)/v29tx_floating_rrc.h
+                 $(srcdir)/v17_v32bis_rx_rrc.h \
+                 $(srcdir)/v17_v32bis_tx_rrc.h \
+                 $(srcdir)/v22bis_rx_1200_rrc.h \
+                 $(srcdir)/v22bis_rx_2400_rrc.h \
+                 $(srcdir)/v22bis_tx_rrc.h \
+                 $(srcdir)/v27ter_rx_2400_rrc.h \
+                 $(srcdir)/v27ter_rx_4800_rrc.h \
+                 $(srcdir)/v27ter_tx_2400_rrc.h \
+                 $(srcdir)/v27ter_tx_4800_rrc.h \
+                 $(srcdir)/v29rx_rrc.h \
+                 $(srcdir)/v29tx_rrc.h
 
 CLEANFILES = ${DISTCLEANFILES}
 MOSTLYCLEANFILES = ${DISTCLEANFILES}
@@ -160,6 +149,7 @@ libspandsp_la_SOURCES = ademco_contactid.c \
                         t4_rx.c \
                         t4_tx.c \
                         t42.c \
+                        t43.c \
                         t81_t82_arith_coding.c \
                         t85_decode.c \
                         t85_encode.c \
@@ -251,6 +241,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
                          spandsp/t4_t6_decode.h \
                          spandsp/t4_t6_encode.h \
                          spandsp/t42.h \
+                         spandsp/t43.h \
                          spandsp/t81_t82_arith_coding.h \
                          spandsp/t85.h \
                          spandsp/telephony.h \
@@ -318,6 +309,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
                          spandsp/private/t4_t6_decode.h \
                          spandsp/private/t4_t6_encode.h \
                          spandsp/private/t42.h \
+                         spandsp/private/t43.h \
                          spandsp/private/t81_t82_arith_coding.h \
                          spandsp/private/t85.h \
                          spandsp/private/time_scale.h \
index eaf6653b5a862f25a0b7cf243967e92ff98c56a0..3cf658e4dffde40f4ca64b353b80aa87fb3db86e 100644 (file)
@@ -511,6 +511,9 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
     s->use_tep = use_tep;
 
     modem_connect_tones_tx_init(&s->connect_tx, MODEM_CONNECT_TONES_FAX_CNG);
+    span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
+    span_log_set_protocol(&s->logging, "FAX modems");
+
     s->tone_callback = tone_callback;
     s->tone_callback_user_data = user_data;
     if (tone_callback)
@@ -521,9 +524,6 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
                                     s->tone_callback_user_data);
     }
     /*endif*/
-    span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
-    span_log_set_protocol(&s->logging, "FAX modems");
-
     dc_restore_init(&s->dc_restore);
 
     s->get_bit = non_ecm_get_bit;
index 8dcafa50e87cb7a2890f889538915931ed763317..2764aa42898870edaee492862cdd27ad85c8d909 100644 (file)
@@ -35,6 +35,7 @@
 
 @SPANDSP_SUPPORT_T42@
 @SPANDSP_SUPPORT_T43@
+@SPANDSP_SUPPORT_V32BIS@
 @SPANDSP_SUPPORT_V34@
 @SPANDSP_SUPPORT_TIFF_FX@
 
 #include <spandsp/v29tx.h>
 #include <spandsp/v17rx.h>
 #include <spandsp/v17tx.h>
-/*#include <spandsp/v32bis.h>*/
+#if defined(SPANDSP_SUPPORT_V32BIS)
+#include <spandsp/v32bis.h>
+#endif
 #include <spandsp/v22bis.h>
 #include <spandsp/v27ter_rx.h>
 #include <spandsp/v27ter_tx.h>
-/*#include <spandsp/v34.h>*/
+#if defined(SPANDSP_SUPPORT_V34)
+#include <spandsp/v34.h>
+#endif
 #include <spandsp/v18.h>
 #include <spandsp/timezone.h>
 #include <spandsp/t4_rx.h>
 #include <spandsp/t81_t82_arith_coding.h>
 #include <spandsp/t85.h>
 #include <spandsp/t42.h>
-/*#include <spandsp/t43.h>*/
+#if defined(SPANDSP_SUPPORT_T43)
+#include <spandsp/t43.h>
+#endif
 #include <spandsp/t30.h>
 #include <spandsp/t30_api.h>
 #include <spandsp/t30_fcf.h>
index d556462a76d328f128790018254021f1892a415e..cb66c2f576309beff4cf971cb9b484121e63f83c 100644 (file)
@@ -35,6 +35,10 @@ struct fax_modems_state_s
 {
     /*! TRUE is talker echo protection should be sent for the image modems */
     int use_tep;
+    /*! \brief The callback function used to report detected tones. */
+    tone_report_func_t tone_callback;
+    /*! \brief A user specified opaque pointer passed to the tone_callback function. */
+    void *tone_callback_user_data;
 
     /*! If TRUE, transmit silence when there is nothing else to transmit. If FALSE return only
         the actual generated audio. Note that this only affects untimed silences. Timed silences
@@ -82,11 +86,6 @@ struct fax_modems_state_s
     /*! \brief */
     dc_restore_state_t dc_restore;
 
-    /*! \brief The callback function used to report detected tones. */
-    tone_report_func_t tone_callback;
-    /*! \brief A user specified opaque pointer passed to the tone_callback function. */
-    void *tone_callback_user_data;
-
     /*! \brief The fast modem type currently in use */
     int fast_modem;
 
index 851c9b950156185291e0c06bd6f85a76e0810103..00bf77c0272148adcd66645bf233dd6c713b7180 100644 (file)
@@ -50,8 +50,12 @@ struct t30_state_s
     int iaf;
     /*! \brief A bit mask of the currently supported modem types. */
     int supported_modems;
-    /*! \brief A bit mask of the currently supported image compression modes. */
+    /*! \brief A bit mask of the currently supported image compression modes for use
+               between FAX entities. */
     int supported_compressions;
+    /*! \brief A bit mask of the currently supported image compression modes for the output
+               of received page images. */
+    int supported_output_compressions;
     /*! \brief A bit mask of the currently supported bi-level image resolutions. */
     int supported_bilevel_resolutions;
     /*! \brief A bit mask of the currently supported gray-scale and colour image resolutions. */
index 229fafab3523b799e2733315c9c18196b997a836..f246c5b3d8cf32a4ebea3c1b4362061c1aa74355 100644 (file)
 #define T30_DCS_BIT_T38_FAX_MODE                            123
 
 /* Bits 124 to 126 specify the T.89 applications profile. */
+#define T30_DIS_BIT_T88_CAPABILITY_1                        124
+#define T30_DCS_BIT_T88_MODE_1                              124
+#define T30_DIS_BIT_T88_CAPABILITY_2                        125
+#define T30_DCS_BIT_T88_MODE_2                              125
+#define T30_DIS_BIT_T88_CAPABILITY_3                        126
+#define T30_DCS_BIT_T88_MODE_3                              126
 
 /* When either bit of 31, 36, 38, 51, 53, 54, 55, 57, 59, 60, 62, 65, 68, 78, 79, 115, 116 and 127 is
    set to "1", ECM must be used. If the value of bit field 92 to 94 is non-zero, then ECM must be used.
index e8e74c2af93d61b4d70444b30dce796f59cac0f9..075a9b221c9925c357c641d317b4e868df935ea2 100644 (file)
@@ -66,10 +66,6 @@ typedef struct
 {
     /*! \brief The FAX modem set for the audio side fo the gateway. */
     fax_modems_state_t modems;
-    /*! \brief CED detector */
-    modem_connect_tones_rx_state_t connect_rx_ced;
-    /*! \brief CNG detector */
-    modem_connect_tones_rx_state_t connect_rx_cng;
 } t38_gateway_audio_state_t;
 
 /*!
diff --git a/libs/spandsp/src/spandsp/private/t43.h b/libs/spandsp/src/spandsp/private/t43.h
new file mode 100644 (file)
index 0000000..b8a4527
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * private/t43.h - ITU T.43 JBIG for gray and colour FAX image processing
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2011 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if !defined(_SPANDSP_PRIVATE_T43_H_)
+#define _SPANDSP_PRIVATE_T43_H_
+
+/* State of a working instance of the T.43 JBIG for gray and colour FAX encoder */
+struct t43_encode_state_s
+{
+    /*! \brief Callback function to read a row of pixels from the image source. */
+    t4_row_read_handler_t row_read_handler;
+    /*! \brief Opaque pointer passed to row_read_handler. */
+    void *row_read_user_data;
+
+    struct lab_params_s lab;
+    struct t85_encode_state_s t85;
+
+    int bit_planes[4];
+
+    int colour_map_entries;
+    uint8_t colour_map[3*256];
+
+    /*! The width of the full image, in pixels */
+    uint32_t xd;
+    /*! The height of the full image, in pixels */
+    uint32_t yd;
+    int x_resolution;
+    int y_resolution;
+
+    /*! \brief Error and flow logging control */
+    logging_state_t logging;
+};
+
+/* State of a working instance of the T.43 JBIG for gray and colour FAX decoder */
+struct t43_decode_state_s
+{
+    /*! A callback routine to handle decoded pixel rows */
+    t4_row_write_handler_t row_write_handler;
+    /*! An opaque pointer passed to row_write_handler() */
+    void *row_write_user_data;
+
+    struct lab_params_s lab;
+    struct t85_decode_state_s t85;
+
+    int bit_planes[4];
+    uint8_t bit_plane_mask;
+    int current_bit_plane;
+    int plane_ptr;
+
+    int colour_map_entries;
+    uint8_t colour_map[3*256];
+
+    int x_resolution;
+    int y_resolution;
+
+    uint8_t *buf;
+    int ptr;
+    int row;
+
+    /*! \brief Error and flow logging control */
+    logging_state_t logging;
+};
+
+#endif
+/*- End of file ------------------------------------------------------------*/
index 58b30e86e97f08d07d38f9b17d5a49a55ab7058f..3dbc5278ed77fa72924a4f47ab9bbc1da7e6e5cc 100644 (file)
@@ -94,6 +94,10 @@ struct t4_rx_state_s
     /*! \brief Opaque pointer passed to row_write_handler. */
     void *row_handler_user_data;
 
+    /*! \brief A bit mask of the currently supported image compression modes for writing
+               to the TIFF file. */
+    int supported_tiff_compressions;
+
     /*! \brief The number of pages transferred to date. */
     int current_page;
 
@@ -111,12 +115,24 @@ struct t4_rx_state_s
     union
     {
         t4_t6_decode_state_t t4_t6;
+        t85_decode_state_t t85;
+#if defined(SPANDSP_SUPPORT_T88)
+        t88_decode_state_t t88;
+#endif
         t42_decode_state_t t42;
 #if defined(SPANDSP_SUPPORT_T43)
         t43_decode_state_t t43;
 #endif
-        t85_decode_state_t t85;
+#if defined(SPANDSP_SUPPORT_T45)
+        t45_decode_state_t t45;
+#endif
     } decoder;
+    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 361ca888712259c3adb7bf57e5362fbd97952483..5ea46b0836fe69a5bcd2c239365d64e78fb09f47 100644 (file)
@@ -146,11 +146,17 @@ struct t4_tx_state_s
     union
     {
         t4_t6_encode_state_t t4_t6;
+        t85_encode_state_t t85;
+#if defined(SPANDSP_SUPPORT_T88)
+        t88_encode_state_t t88;
+#endif
         t42_encode_state_t t42;
 #if defined(SPANDSP_SUPPORT_T43)
         t43_encode_state_t t43;
 #endif
-        t85_encode_state_t t85;
+#if defined(SPANDSP_SUPPORT_T45)
+        t45_encode_state_t t45;
+#endif
     } encoder;
 
     image_translate_state_t translator;
@@ -160,6 +166,11 @@ struct t4_tx_state_s
     uint8_t *colour_map;
     int colour_map_entries;
 
+    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_tx_metadata_t metadata;
 
index 3639ca6715009871e35124c7e674bf85e9247802..a991cc5107e491546cd3693ff921dc91e56926d3 100644 (file)
@@ -48,7 +48,6 @@ struct v18_state_s
     int baudot_tx_shift;
     int tx_signal_on;
     uint8_t next_byte;
-    int byte_no;
 
     fsk_rx_state_t fskrx;
     dtmf_rx_state_t dtmfrx;
index f4f8040beb82d995dce96d4191c53bf3474f6868..da3ef01a308403cb4dcce7687bc534af1fde6a9c 100644 (file)
@@ -439,12 +439,10 @@ SPAN_DECLARE(int) t30_set_ecm_capability(t30_state_t *s, int enabled);
 /*! Specify the output encoding for TIFF files created during FAX reception.
     \brief Specify the output encoding for TIFF files created during FAX reception.
     \param s The T.30 context.
-    \param encoding The coding required. The options are T4_COMPRESSION_T4_1D,
-           T4_COMPRESSION_T4_2D, T4_COMPRESSION_T6. T6 is usually the
-           densest option, but support for it is broken in a number of software
-           packages.
+    \param supported_compressions Bit field list of the supported compression types, for
+           output of received page images.
     \return 0 if OK, else -1. */
-SPAN_DECLARE(int) t30_set_rx_encoding(t30_state_t *s, int encoding);
+SPAN_DECLARE(int) t30_set_supported_output_compressions(t30_state_t *s, int supported_compressions);
 
 /*! Specify the minimum scan line time supported by a T.30 context.
     \brief Specify minimum scan line time.
diff --git a/libs/spandsp/src/spandsp/t43.h b/libs/spandsp/src/spandsp/t43.h
new file mode 100644 (file)
index 0000000..decb928
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * t43.h - ITU T.43 JBIG for grey and colour FAX image processing
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2011 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*! \file */
+
+#if !defined(_SPANDSP_T43_H_)
+#define _SPANDSP_T43_H_
+
+/*! \page t43_page T.43 (JBIG for gray and colour FAX) image compression and decompression
+
+\section t43_page_sec_1 What does it do?
+
+\section t43_page_sec_1 How does it work?
+*/
+
+/*! State of a working instance of the T.43 encoder */
+typedef struct t43_encode_state_s t43_encode_state_t;
+
+/*! State of a working instance of the T.43 decoder */
+typedef struct t43_decode_state_s t43_decode_state_t;
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+SPAN_DECLARE(const char *) t43_image_type_to_str(int type);
+
+SPAN_DECLARE(void) t43_encode_set_options(t43_encode_state_t *s,
+                                          uint32_t l0,
+                                          int mx,
+                                          int options);
+
+SPAN_DECLARE(int) t43_encode_set_image_width(t43_encode_state_t *s, uint32_t image_width);
+
+SPAN_DECLARE(int) t43_encode_set_image_length(t43_encode_state_t *s, uint32_t length);
+
+SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s);
+
+SPAN_DECLARE(void) t43_encode_comment(t43_encode_state_t *s, const uint8_t comment[], size_t len);
+
+/*! \brief Check if we are at the end of the current document page.
+    \param s The T.43 context.
+    \return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */
+SPAN_DECLARE(int) t43_encode_image_complete(t43_encode_state_t *s);
+
+SPAN_DECLARE(int) t43_encode_get(t43_encode_state_t *s, uint8_t buf[], size_t max_len);
+
+SPAN_DECLARE(uint32_t) t43_encode_get_image_width(t43_encode_state_t *s);
+
+SPAN_DECLARE(uint32_t) t43_encode_get_image_length(t43_encode_state_t *s);
+
+SPAN_DECLARE(int) t43_encode_get_compressed_image_size(t43_encode_state_t *s);
+
+SPAN_DECLARE(int) t43_encode_set_row_read_handler(t43_encode_state_t *s,
+                                                  t4_row_read_handler_t handler,
+                                                  void *user_data);
+
+/*! Get the logging context associated with a T.43 encode context.
+    \brief Get the logging context associated with a T.43 encode context.
+    \param s The T.43 encode context.
+    \return A pointer to the logging context */
+SPAN_DECLARE(logging_state_t *) t43_encode_get_logging_state(t43_encode_state_t *s);
+
+/*! \brief Restart a T.43 encode context.
+    \param s The T.43 context.
+    \param image image_width The image width, in pixels.
+    \param image image_width The image length, in pixels.
+    \return 0 for success, otherwise -1. */
+SPAN_DECLARE(int) t43_encode_restart(t43_encode_state_t *s, uint32_t image_width, uint32_t image_length);
+
+/*! \brief Prepare to encode an image in T.43 format.
+    \param s The T.43 context.
+    \param image_width Image width, in pixels.
+    \param image_length Image length, in pixels.
+    \param handler A callback routine to handle encoded image rows.
+    \param user_data An opaque pointer passed to handler.
+    \return A pointer to the context, or NULL if there was a problem. */
+SPAN_DECLARE(t43_encode_state_t *) t43_encode_init(t43_encode_state_t *s,
+                                                   uint32_t image_width,
+                                                   uint32_t image_length,
+                                                   t4_row_read_handler_t handler,
+                                                   void *user_data);
+
+/*! \brief Release a T.43 encode context.
+    \param s The T.43 encode context.
+    \return 0 for OK, else -1. */
+SPAN_DECLARE(int) t43_encode_release(t43_encode_state_t *s);
+
+/*! \brief Free a T.43 encode context.
+    \param s The T.43 encode context.
+    \return 0 for OK, else -1. */
+SPAN_DECLARE(int) t43_encode_free(t43_encode_state_t *s);
+
+SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_t len);
+
+SPAN_DECLARE(void) t43_decode_rx_status(t43_decode_state_t *s, int status);
+
+/*! \brief Decode a chunk of T.43 data.
+    \param s The T.43 context.
+    \param data The data to be decoded.
+    \param len The length of the data to be decoded.
+    \return 0 for OK. */
+SPAN_DECLARE(int) t43_decode_put(t43_decode_state_t *s, const uint8_t data[], size_t len);
+
+/*! \brief Set the row handler routine.
+    \param s The T.43 context.
+    \param handler A callback routine to handle decoded image rows.
+    \param user_data An opaque pointer passed to handler.
+    \return 0 for OK. */
+SPAN_DECLARE(int) t43_decode_set_row_write_handler(t43_decode_state_t *s,
+                                                   t4_row_write_handler_t handler,
+                                                   void *user_data);
+
+/*! \brief Set the comment handler routine.
+    \param s The T.43 context.
+    \param max_comment_len The maximum length of comment to be passed to the handler.
+    \param handler A callback routine to handle decoded comment.
+    \param user_data An opaque pointer passed to handler.
+    \return 0 for OK. */
+SPAN_DECLARE(int) t43_decode_set_comment_handler(t43_decode_state_t *s,
+                                                 uint32_t max_comment_len,
+                                                 t4_row_write_handler_t handler,
+                                                 void *user_data);
+
+SPAN_DECLARE(int) t43_decode_set_image_size_constraints(t43_decode_state_t *s,
+                                                        uint32_t max_xd,
+                                                        uint32_t max_yd);
+
+/*! \brief Get the width of the image.
+    \param s The T.43 context.
+    \return The width of the image, in pixels. */
+SPAN_DECLARE(uint32_t) t43_decode_get_image_width(t43_decode_state_t *s);
+
+/*! \brief Get the length of the image.
+    \param s The T.43 context.
+    \return The length of the image, in pixels. */
+SPAN_DECLARE(uint32_t) t43_decode_get_image_length(t43_decode_state_t *s);
+
+SPAN_DECLARE(int) t43_decode_get_compressed_image_size(t43_decode_state_t *s);
+
+/*! Get the logging context associated with a T.43 decode context.
+    \brief Get the logging context associated with a T.43 decode context.
+    \param s The T.43 decode context.
+    \return A pointer to the logging context */
+SPAN_DECLARE(logging_state_t *) t43_decode_get_logging_state(t43_decode_state_t *s);
+
+SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s);
+
+/*! \brief Prepare to decode an image in T.43 format.
+    \param s The T.43 context.
+    \param handler A callback routine to handle decoded image rows.
+    \param user_data An opaque pointer passed to handler.
+    \return A pointer to the context, or NULL if there was a problem. */
+SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s,
+                                                   t4_row_write_handler_t handler,
+                                                   void *user_data);
+
+/*! \brief Release a T.43 decode context.
+    \param s The T.43 decode context.
+    \return 0 for OK, else -1. */
+SPAN_DECLARE(int) t43_decode_release(t43_decode_state_t *s);
+
+/*! \brief Free a T.43 decode context.
+    \param s The T.43 decode context.
+    \return 0 for OK, else -1. */
+SPAN_DECLARE(int) t43_decode_free(t43_decode_state_t *s);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/
index 6767f902d41e6670dbbf8b2875d7757cde70e4db..8ff25d7927f8c50a2e043fb8a5953e213c5991e2 100644 (file)
@@ -67,47 +67,49 @@ typedef enum
     /*! T.42 + T.81 + T.30 Annex E colour JPEG coding */
     T4_COMPRESSION_T42_T81 = 8,
     /*! T.42 + T.81 + T.30 Annex K colour sYCC-JPEG coding */
-    T4_COMPRESSION_SYCC_T81 = 9
+    T4_COMPRESSION_SYCC_T81 = 9,
+    /*! T.88 monochrome JBIG2 compression */
+    T4_COMPRESSION_T88 = 10
 } t4_image_compression_t;
 
 enum
 {
     /*! No compression */
-    T30_SUPPORT_COMPRESSION_NONE = 0x01,
+    T4_SUPPORT_COMPRESSION_NONE = 0x01,
     /*! T.1 1D compression */
-    T30_SUPPORT_COMPRESSION_T4_1D = 0x02,
+    T4_SUPPORT_COMPRESSION_T4_1D = 0x02,
     /*! T.4 2D compression */
-    T30_SUPPORT_COMPRESSION_T4_2D = 0x04,
+    T4_SUPPORT_COMPRESSION_T4_2D = 0x04,
     /*! T.6 2D compression */
-    T30_SUPPORT_COMPRESSION_T6 = 0x08,
+    T4_SUPPORT_COMPRESSION_T6 = 0x08,
     /*! T.85 monochrome JBIG compression, with fixed L0 */
-    T30_SUPPORT_COMPRESSION_T85 = 0x10,
+    T4_SUPPORT_COMPRESSION_T85 = 0x10,
     /*! T.85 monochrome JBIG compression, with variable L0 */
-    T30_SUPPORT_COMPRESSION_T85_L0 = 0x20,
+    T4_SUPPORT_COMPRESSION_T85_L0 = 0x20,
     /*! T.43 colour JBIG compression */
-    T30_SUPPORT_COMPRESSION_T43 = 0x40,
+    T4_SUPPORT_COMPRESSION_T43 = 0x40,
     /*! T.45 run length colour compression */
-    T30_SUPPORT_COMPRESSION_T45 = 0x80,
+    T4_SUPPORT_COMPRESSION_T45 = 0x80,
     /*! T.81 + T.30 Annex E colour JPEG compression */
-    T30_SUPPORT_COMPRESSION_T42_T81 = 0x100,
+    T4_SUPPORT_COMPRESSION_T42_T81 = 0x100,
     /*! T.81 + T.30 Annex K colour sYCC-JPEG compression */
-    T30_SUPPORT_COMPRESSION_SYCC_T81 = 0x200,
+    T4_SUPPORT_COMPRESSION_SYCC_T81 = 0x200,
     /*! T.88 monochrome JBIG2 compression */
-    T30_SUPPORT_COMPRESSION_T88 = 0x400,
+    T4_SUPPORT_COMPRESSION_T88 = 0x400,
     /*! Gray-scale support by multi-level codecs */
-    T30_SUPPORT_COMPRESSION_GRAYSCALE = 0x1000000,
+    T4_SUPPORT_COMPRESSION_GRAYSCALE = 0x1000000,
     /*! Colour support by multi-level codecs */
-    T30_SUPPORT_COMPRESSION_COLOUR = 0x2000000,
+    T4_SUPPORT_COMPRESSION_COLOUR = 0x2000000,
     /*! 12 bit mode for gray-scale and colour */
-    T30_SUPPORT_COMPRESSION_12BIT = 0x4000000,
+    T4_SUPPORT_COMPRESSION_12BIT = 0x4000000,
     /*! Convert a colour image to a gray-scale one */
-    T30_SUPPORT_COMPRESSION_COLOUR_TO_GRAY = 0x8000000,
+    T4_SUPPORT_COMPRESSION_COLOUR_TO_GRAY = 0x8000000,
     /*! Dither a gray-scale image down a simple bilevel image, with rescaling to fit a FAX page */
     T30_SUPPORT_GRAY_TO_BILEVEL = 0x10000000,
     /*! Dither a colour image down a simple bilevel image, with rescaling to fit a FAX page */
     T30_SUPPORT_COLOUR_TO_BILEVEL = 0x20000000,
     /*! Rescale an image (except a bi-level image) to fit a permitted FAX width when necessary */
-    T30_SUPPORT_COMPRESSION_RESCALING = 0x40000000
+    T4_SUPPORT_COMPRESSION_RESCALING = 0x40000000
 };
 
 /*! Image type */
@@ -561,9 +563,9 @@ SPAN_DECLARE(logging_state_t *) t4_rx_get_logging_state(t4_rx_state_t *s);
 /*! \brief Prepare for reception of a document.
     \param s The T.4 context.
     \param file The name of the file to be received.
-    \param output_encoding The output encoding.
+    \param supported_compressions The compression schemes supported for output to a TIFF file.
     \return A pointer to the context, or NULL if there was a problem. */
-SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int output_encoding);
+SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int supported_compressions);
 
 /*! \brief End reception of a document. Tidy up and close the file.
            This should be used to end T.4 reception started with t4_rx_init.
index 799cadbfcd77ec5c80bbaff38a5a35e1617bc492..e7d07189b0e6552d44cb3babad29b963a1e6c584 100644 (file)
@@ -30,8 +30,8 @@
 #endif
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <inttypes.h>
+#include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
 #include <time.h>
@@ -1195,9 +1195,9 @@ int t30_build_dis_or_dtc(t30_state_t *s)
     /* No scan-line padding required, but some may be specified by the application. */
     set_ctrl_bits(s->local_dis_dtc_frame, s->local_min_scan_time_code, T30_DIS_BIT_MIN_SCAN_LINE_TIME_CAPABILITY_1);
 
-    if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D))
+    if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T4_2D))
         set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE);
-    if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_NONE))
+    if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_NONE))
         set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_UNCOMPRESSED_CAPABLE);
     if (s->ecm_allowed)
     {
@@ -1206,46 +1206,46 @@ int t30_build_dis_or_dtc(t30_state_t *s)
 
         /* Only offer the option of fancy compression schemes, if we are
            also offering the ECM option needed to support them. */
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T6))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T6))
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE);
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T85))
         {
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE);
             /* Bit 79 set with bit 78 clear is invalid, so only check for L0
                support here. */
-            if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85_L0))
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T85_L0))
                 set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE);
         }
 
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_COLOUR))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_COLOUR))
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE);
 
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T42_T81))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T42_T81))
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T43))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T43))
         {
             /* Note 25 of table 2/T.30 */
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE);
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
         }
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T45))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T45))
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE);
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_SYCC_T81))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_SYCC_T81))
         {
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE);
         }
-        //if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T88))
+        //if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T88))
         //{
         //    set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_1);
         //    set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_2);
         //    set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_3);
         //}
 
-        if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_12BIT))
+        if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_12BIT))
             set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE);
 
-        //if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_NO_SUBSAMPLING))
+        //if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_NO_SUBSAMPLING))
         //    set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
 
         /* No custom illuminant */
@@ -1345,8 +1345,8 @@ int t30_build_dis_or_dtc(t30_state_t *s)
     if ((s->supported_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_200))
     {
         set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE);
-        //if ((s->supported_colour_resolutions & T4_SUPPORT_RESOLUTION_200_200))
-        //    set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_???_CAPABLE);
+        if ((s->supported_colour_resolutions & T4_SUPPORT_RESOLUTION_200_200))
+            set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE);
     }
     /* Standard FAX resolution bi-level image support goes without saying */
     if ((s->supported_colour_resolutions & T4_SUPPORT_RESOLUTION_100_100))
@@ -1421,14 +1421,14 @@ static int build_dcs(t30_state_t *s)
     int bad;
     int row_squashing_ratio;
     int use_bilevel;
-    //int image_type;
+    int image_type;
 
     /* Reacquire page information, in case the image was resized, flattened, etc. */
     s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
     s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
-    //s->current_page_resolution = t4_tx_get_resolution(&s->t4.tx);
+    s->current_page_resolution = t4_tx_get_resolution(&s->t4.tx);
     s->image_width = t4_tx_get_image_width(&s->t4.tx);
-    //image_type = t4_tx_get_image_type(&s->t4.tx);
+    image_type = t4_tx_get_image_type(&s->t4.tx);
 
     /* Make a DCS frame based on local issues and the latest received DIS/DTC frame.
        Negotiate the result based on what both parties can do. */
@@ -1483,22 +1483,24 @@ static int build_dcs(t30_state_t *s)
 #endif
     case T4_COMPRESSION_T42_T81:
         set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T81_MODE);
-        //if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
-        //    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
-        //if (image_type == T4_IMAGE_TYPE_GRAY_12BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
-        //    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
+        if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
+        if (image_type == T4_IMAGE_TYPE_GRAY_12BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
         //if (???????? & T4_COMPRESSION_?????))
         //    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
+        //if (???????? & T4_COMPRESSION_?????))
+        //    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES);
         set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
         use_bilevel = FALSE;
         break;
 #if defined(SPANDSP_SUPPORT_T43)
     case T4_COMPRESSION_T43:
         set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE);
-        //if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
-        //    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
-        //if (image_type == T4_IMAGE_TYPE_GRAY_12BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
-        //    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
+        if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
+        if (image_type == T4_IMAGE_TYPE_GRAY_12BIT  ||  image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
         //if (???????? & T4_COMPRESSION_?????))
         //    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
         set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
@@ -1523,159 +1525,139 @@ static int build_dcs(t30_state_t *s)
     /* Set the Y resolution bits */
     row_squashing_ratio = 1;
     bad = T30_ERR_NORESSUPPORT;
-    if (use_bilevel)
+    if ((use_bilevel  &&  (s->current_page_resolution & s->mutual_bilevel_resolutions))
+        ||
+        (!use_bilevel  &&  (s->current_page_resolution & s->mutual_colour_resolutions)))
     {
-        switch (s->y_resolution)
+        /* The resolution is supported by both parties */
+        switch (s->current_page_resolution)
         {
-        case T4_Y_RESOLUTION_1200:
-            switch (s->x_resolution)
-            {
-            case T4_X_RESOLUTION_1200:
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_1200_1200))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                }
-                break;
-            case T4_X_RESOLUTION_600:
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_1200))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                }
-                break;
-            }
-            break;
-        case T4_Y_RESOLUTION_800:
-            switch (s->x_resolution)
-            {
-            case T4_X_RESOLUTION_R16:
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_800))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                }
-                break;
-            }
+        case T4_RESOLUTION_1200_1200:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            if (!use_bilevel)
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200);
+            break;
+        case T4_RESOLUTION_600_1200:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            break;
+        case T4_RESOLUTION_600_600:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            if (!use_bilevel)
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600);
+            break;
+        case T4_RESOLUTION_400_800:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            break;
+        case T4_RESOLUTION_400_400:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            if (!use_bilevel)
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
+            break;
+        case T4_RESOLUTION_300_600:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            break;
+        case T4_RESOLUTION_300_300:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            if (!use_bilevel)
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
+            break;
+        case T4_RESOLUTION_200_400:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            break;
+        case T4_RESOLUTION_200_200:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            if (!use_bilevel)
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
+            break;
+        case T4_RESOLUTION_200_100:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            break;
+        case T4_RESOLUTION_100_100:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+            if (!use_bilevel)
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100);
+            break;
+        case T4_RESOLUTION_R16_SUPERFINE:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
+            break;
+        case T4_RESOLUTION_R8_SUPERFINE:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
+            break;
+        case T4_RESOLUTION_R8_FINE:
+            set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
+            break;
+        case T4_RESOLUTION_R8_STANDARD:
+            /* Nothing special to set */
             break;
-        case T4_Y_RESOLUTION_600:
-            switch (s->x_resolution)
-            {
-            case T4_X_RESOLUTION_600:
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_600))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                }
-                break;
-            case T4_X_RESOLUTION_300:
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_600))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                }
-                break;
-            }
-            break;
-        case T4_Y_RESOLUTION_300:
-            switch (s->x_resolution)
-            {
-            case T4_X_RESOLUTION_300:
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_300))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                }
-                break;
-            }
-            break;
-        case T4_Y_RESOLUTION_SUPERFINE:
-        case T4_Y_RESOLUTION_400:
-            if (s->x_resolution == T4_X_RESOLUTION_400  &&  s->y_resolution == T4_Y_RESOLUTION_400)
-            {
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_400))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                    break;
-                }
-            }
-            else if (s->x_resolution == T4_X_RESOLUTION_R16  &&  s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
-            {
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R16_SUPERFINE))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
-                    bad = T30_ERR_OK;
-                    break;
-                }
-            }
-            else if (s->x_resolution == T4_X_RESOLUTION_200  &&  s->y_resolution == T4_Y_RESOLUTION_400)
+        }
+        bad = T30_ERR_OK;
+    }
+    else
+    {
+#if 0
+        /* Deal with resolution fudging */
+        if ((s->current_page_resolution & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
+        {
+            if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100)))
             {
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_400))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                    break;
-                }
+                /* Fudge between imperial and metric */
             }
-            else if (s->x_resolution == T4_X_RESOLUTION_R8  &&  s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
+        }
+        else if ((s->current_page_resolution & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100))
+        {
+            if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
             {
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R8_SUPERFINE))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
-                    bad = T30_ERR_OK;
-                    break;
-                }
+                /* Fudge between imperial and metric */
             }
-            row_squashing_ratio <<= 1;
-            /* Fall through */
-        case T4_Y_RESOLUTION_FINE:
-        case T4_Y_RESOLUTION_200:
-            if (s->x_resolution == T4_X_RESOLUTION_200  &&  s->y_resolution == T4_Y_RESOLUTION_200)
+        }
+#endif
+        /* Deal with squashing options */
+        if ((s->current_page_resolution & T4_RESOLUTION_R8_SUPERFINE))
+        {
+            if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_FINE))
             {
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_200))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
-                    bad = T30_ERR_OK;
-                    break;
-                }
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
+                row_squashing_ratio = 2;
+                bad = T30_ERR_OK;
             }
-            else if (s->x_resolution == T4_X_RESOLUTION_R8  &&  s->y_resolution == T4_Y_RESOLUTION_FINE)
+            else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
             {
-                if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R8_FINE))
-                {
-                    set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
-                    bad = T30_ERR_OK;
-                    break;
-                }
+                row_squashing_ratio = 4;
+                bad = T30_ERR_OK;
             }
-            row_squashing_ratio <<= 1;
-            /* Fall through */
-        default:
-        case T4_Y_RESOLUTION_STANDARD:
-        case T4_Y_RESOLUTION_100:
-            if (s->x_resolution == T4_X_RESOLUTION_R8  &&  s->y_resolution == T4_Y_RESOLUTION_STANDARD)
+        }
+        else if ((s->current_page_resolution & T4_RESOLUTION_R8_FINE)  &&  (s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
+        {
+            row_squashing_ratio = 2;
+            bad = T30_ERR_OK;
+        }
+        else if ((s->current_page_resolution & T4_RESOLUTION_200_400))
+        {
+            if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_200))
             {
-                /* No bits to set for this */
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
+                row_squashing_ratio = 2;
                 bad = T30_ERR_OK;
-                break;
             }
-            else if (s->x_resolution == T4_X_RESOLUTION_200  &&  s->y_resolution == T4_Y_RESOLUTION_100)
+            else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
             {
-                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
+                row_squashing_ratio = 4;
                 bad = T30_ERR_OK;
-                break;
             }
-            break;
+        }
+        else if ((s->current_page_resolution & T4_RESOLUTION_200_200)  &&  (s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
+        {
+            row_squashing_ratio = 2;
+            bad = T30_ERR_OK;
         }
     }
 
@@ -1768,10 +1750,15 @@ static int build_dcs(t30_state_t *s)
     /* Deal with the image length */
     /* If the other end supports unlimited length, then use that. Otherwise, if the other end supports
        B4 use that, as its longer than the default A4 length. */
+printf("Size1 0x%x\n", s->mutual_image_sizes);
     if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
         set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_UNLIMITED_LENGTH);
     else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_B4))
         set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_B4_LENGTH);
+    else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_US_LETTER))
+        set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NORTH_AMERICAN_LETTER);
+    else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_US_LEGAL))
+        set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NORTH_AMERICAN_LEGAL);
 
     if (s->error_correcting_mode)
         set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_ECM_MODE);
@@ -1845,40 +1832,40 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
     if (!s->error_correcting_mode)
     {
         /* Remove any compression schemes which need error correction to work. */
-        s->mutual_compressions &= (0xF0000000 | T30_SUPPORT_COMPRESSION_NONE | T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D);
+        s->mutual_compressions &= (0xF0000000 | T4_SUPPORT_COMPRESSION_NONE | T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D);
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T4_2D;
     }
     else
     {
         /* Check the bi-level capabilities */
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T4_2D;
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T6;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T6;
         /* T.85 L0 capable without T.85 capable is an invalid combination, so let
            just zap both capabilities if the far end is not T.85 capable. */
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE))
-            s->mutual_compressions &= ~(T30_SUPPORT_COMPRESSION_T85 | T30_SUPPORT_COMPRESSION_T85_L0);
+            s->mutual_compressions &= ~(T4_SUPPORT_COMPRESSION_T85 | T4_SUPPORT_COMPRESSION_T85_L0);
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T85_L0;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T85_L0;
 
         /* Check for full colour or only gray-scale from the multi-level codecs */
-        //if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE))
-        //    s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_COLOUR;
+        if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE))
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_COLOUR;
 
         /* Check the colour capabilities */
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T42_T81;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T42_T81;
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_SYCC_T81;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_SYCC_T81;
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T43;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T43;
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T45;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T45;
 
         if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
-            s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_12BIT;
+            s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_12BIT;
         //if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
         //    ???? = T4_COMPRESSION_T42_T81_SUBSAMPLING;
 
@@ -1975,9 +1962,9 @@ 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_A4_B4_LENGTH_CAPABLE))
             s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_B4;
     }
-    if (!test_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LETTER_CAPABLE))
+    if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LETTER_CAPABLE))
         s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LETTER;
-    if (!test_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LEGAL_CAPABLE))
+    if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LEGAL_CAPABLE))
         s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LEGAL;
 
     switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
@@ -2067,6 +2054,7 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
     s->x_resolution = -1;
     s->y_resolution = -1;
     s->current_page_resolution = 0;
+    s->line_encoding = -1;
     x = -1;
     if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE)
         ||
@@ -2081,17 +2069,28 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
         /* Note 35 of Table 2/T.30 */
         if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE))
         {
-            /* We are going to work in full colour mode */
+            if ((s->supported_colour_resolutions & T4_SUPPORT_COMPRESSION_COLOUR))
+            {
+                /* We are going to work in full colour mode */
+            }
         }
 
         if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_12BIT_COMPONENT))
         {
-            /* We are going to work in 12 bit mode */
+            if ((s->supported_colour_resolutions & T4_SUPPORT_COMPRESSION_12BIT))
+            {
+                /* We are going to work in 12 bit mode */
+            }
         }
 
         if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING))
         {
-            //???? = T30_SUPPORT_COMPRESSION_T42_T81_SUBSAMPLING;
+            //???? = T4_SUPPORT_COMPRESSION_T42_T81_SUBSAMPLING;
+        }
+
+        if (!test_ctrl_bit(dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES))
+        {
+            //???? = T4_SUPPORT_COMPRESSION_T42_T81_HUFFMAN;
         }
 
         if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200))
@@ -2154,6 +2153,28 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
                 x = 0;
             }
         }
+
+        /* Check which compression the far end has decided to use. */
+        if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T42_T81))
+                s->line_encoding = T4_COMPRESSION_T42_T81;
+        }
+        else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T43_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T43))
+                s->line_encoding = T4_COMPRESSION_T43;
+        }
+        else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T45_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T45))
+                s->line_encoding = T4_COMPRESSION_T45;
+        }
+        else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_SYCC_T81_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_SYCC_T81))
+                s->line_encoding = T4_COMPRESSION_SYCC_T81;
+        }
     }
     else
     {
@@ -2304,7 +2325,50 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
                 x = 1;
             }
         }
+
+        /* Check which compression the far end has decided to use. */
+        if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T88_MODE_1)
+            ||
+            test_ctrl_bit(dcs_frame, T30_DCS_BIT_T88_MODE_2)
+            ||
+            test_ctrl_bit(dcs_frame, T30_DCS_BIT_T88_MODE_3))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T88))
+                s->line_encoding = T4_COMPRESSION_T88;
+        }
+        if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_L0_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T85_L0))
+                s->line_encoding = T4_COMPRESSION_T85_L0;
+        }
+        else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T85))
+                s->line_encoding = T4_COMPRESSION_T85;
+        }
+        else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T6_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T6))
+                s->line_encoding = T4_COMPRESSION_T6;
+        }
+        else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_2D_MODE))
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T4_2D))
+                s->line_encoding = T4_COMPRESSION_T4_2D;
+        }
+        else
+        {
+            if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T4_1D))
+                s->line_encoding = T4_COMPRESSION_T4_1D;
+        }
+    }
+
+    if (s->line_encoding == -1)
+    {
+        t30_set_status(s, T30_ERR_INCOMPATIBLE);
+        return -1;
     }
+    span_log(&s->logging, SPAN_LOG_FLOW, "Far end selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
 
     if (x < 0)
     {
@@ -2313,43 +2377,8 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
     }
 
     s->image_width = widths[x][dcs_frame[5] & (DISBIT2 | DISBIT1)];
+    /* We don't care that much about the image length control bits. Just accept what arrives */
 
-    /* Check which compression the far end has decided to use. */
-#if defined(SPANDSP_SUPPORT_T42)
-    if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE))
-    {
-        s->line_encoding = T4_COMPRESSION_T42_T81;
-    }
-    else
-#endif
-#if defined(SPANDSP_SUPPORT_T43)
-    if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T43_MODE))
-    {
-        s->line_encoding = T4_COMPRESSION_T43;
-    }
-    else
-#endif
-    if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_L0_MODE))
-    {
-        s->line_encoding = T4_COMPRESSION_T85_L0;
-    }
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_MODE))
-    {
-        s->line_encoding = T4_COMPRESSION_T85;
-    }
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T6_MODE))
-    {
-        s->line_encoding = T4_COMPRESSION_T6;
-    }
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_2D_MODE))
-    {
-        s->line_encoding = T4_COMPRESSION_T4_2D;
-    }
-    else
-    {
-        s->line_encoding = T4_COMPRESSION_T4_1D;
-    }
-    span_log(&s->logging, SPAN_LOG_FLOW, "Far end selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
     if (!test_ctrl_bit(dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT))
         span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Remote is not requesting receive in DCS\n");
 
@@ -2749,13 +2778,13 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
     }
 
     /* Choose a compression scheme from amongst those mutually available */
-    if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85_L0))
+    if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T85_L0))
         s->line_encoding = T4_COMPRESSION_T85_L0;
-    else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85))
+    else if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T85))
         s->line_encoding = T4_COMPRESSION_T85;
-    else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T6))
+    else if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T6))
         s->line_encoding = T4_COMPRESSION_T6;
-    else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T4_2D))
+    else if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T4_2D))
         s->line_encoding = T4_COMPRESSION_T4_2D;
     else
         s->line_encoding = T4_COMPRESSION_T4_1D;
@@ -6766,7 +6795,7 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
 
     /* Default to the basic modems. */
     s->supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
-    s->supported_compressions = T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D;
+    s->supported_compressions = T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D;
     s->supported_bilevel_resolutions = T4_SUPPORT_RESOLUTION_R8_STANDARD
                                      | T4_SUPPORT_RESOLUTION_R8_FINE
                                      | T4_SUPPORT_RESOLUTION_R8_SUPERFINE;
index 43f440fd328a869fae3d726aa6d3404137246e4c..045ba659610dba651e4a107020a48090aa178e94 100644 (file)
@@ -646,19 +646,11 @@ SPAN_DECLARE(int) t30_set_ecm_capability(t30_state_t *s, int enabled)
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(int) t30_set_rx_encoding(t30_state_t *s, int encoding)
+SPAN_DECLARE(int) t30_set_supported_output_compressions(t30_state_t *s, int supported_compressions)
 {
-    switch (encoding)
-    {
-    case T4_COMPRESSION_T4_1D:
-    case T4_COMPRESSION_T4_2D:
-    case T4_COMPRESSION_T6:
-    //case T4_COMPRESSION_T85:
-    //case T4_COMPRESSION_T85_L0:
-        s->output_encoding = encoding;
-        return 0;
-    }
-    return -1;
+    s->supported_output_compressions = supported_compressions;
+    s->output_encoding = supported_compressions;
+    return 0;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -694,14 +686,14 @@ SPAN_DECLARE(int) t30_set_supported_modems(t30_state_t *s, int supported_modems)
 SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_compressions)
 {
     /* Mask out the ones we actually support today. */
-    supported_compressions &= T30_SUPPORT_COMPRESSION_T4_1D
-                            | T30_SUPPORT_COMPRESSION_T4_2D
-                            | T30_SUPPORT_COMPRESSION_T6
-                            | T30_SUPPORT_COMPRESSION_T85
-                            | T30_SUPPORT_COMPRESSION_T85_L0
-                            //| T30_SUPPORT_COMPRESSION_T81
+    supported_compressions &= T4_SUPPORT_COMPRESSION_T4_1D
+                            | T4_SUPPORT_COMPRESSION_T4_2D
+                            | T4_SUPPORT_COMPRESSION_T6
+                            | T4_SUPPORT_COMPRESSION_T85
+                            | T4_SUPPORT_COMPRESSION_T85_L0
+                            //| T4_SUPPORT_COMPRESSION_T81
 #if defined(SPANDSP_SUPPORT_T43)
-                            | T30_SUPPORT_COMPRESSION_T43
+                            | T4_SUPPORT_COMPRESSION_T43
 #endif
                             | 0;
     s->supported_compressions = supported_compressions;
diff --git a/libs/spandsp/src/t43.c b/libs/spandsp/src/t43.c
new file mode 100644 (file)
index 0000000..7ba3e25
--- /dev/null
@@ -0,0 +1,845 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * t43.c - ITU T.43 JBIG for grey and colour FAX image processing
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2011, 2013 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*! \file */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tiffio.h>
+#if defined(HAVE_TGMATH_H)
+#include <tgmath.h>
+#endif
+#if defined(HAVE_MATH_H)
+#include <math.h>
+#endif
+#include <time.h>
+#include "floating_fudge.h"
+#include <jpeglib.h>
+#include <setjmp.h>
+
+#include "spandsp/telephony.h"
+#include "spandsp/logging.h"
+#include "spandsp/async.h"
+#include "spandsp/timezone.h"
+#include "spandsp/t4_rx.h"
+#include "spandsp/t4_tx.h"
+#include "spandsp/t81_t82_arith_coding.h"
+#include "spandsp/t85.h"
+#include "spandsp/t42.h"
+#include "spandsp/t43.h"
+
+#include "spandsp/private/logging.h"
+#include "spandsp/private/t81_t82_arith_coding.h"
+#include "spandsp/private/t85.h"
+#include "spandsp/private/t42.h"
+#include "spandsp/private/t43.h"
+
+#include "t42_t43_local.h"
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(TRUE)
+#define TRUE (!FALSE)
+#endif
+
+SPAN_DECLARE(const char *) t43_image_type_to_str(int type)
+{
+    switch (type)
+    {
+    case 0:
+        return "1 bit/colour image (RGB primaries)";
+    case 1:
+        return "1 bit/colour image (CMY primaries)";
+    case 2:
+        return "1 bit/colour image (CMYK primaries)";
+    case 16:
+        return "Palettized colour image (CIELAB 8 bits/component precision table)";
+    case 17:
+        return "Palettized colour image (CIELAB 12 bits/component precision table)";
+    case 32:
+        return "Gray-scale image (using L*)";
+    case 48:
+        return "Continuous-tone colour image (CIELAB)";
+    }
+    return "???";
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ uint16_t pack_16(const uint8_t *s)
+{
+    uint16_t value;
+
+    value = ((uint16_t) s[0] << 8) | (uint16_t) s[1];
+    return value;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ uint32_t pack_32(const uint8_t *s)
+{
+    uint32_t value;
+
+    value = ((uint32_t) s[0] << 24) | ((uint32_t) s[1] << 16) | ((uint32_t) s[2] << 8) | (uint32_t) s[3];
+    return value;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int unpack_16(uint8_t *s, uint16_t value)
+{
+    s[0] = (value >> 8) & 0xFF;
+    s[1] = value & 0xFF;
+    return sizeof(uint16_t);
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int unpack_32(uint8_t *s, uint32_t value)
+{
+    s[0] = (value >> 24) & 0xFF;
+    s[1] = (value >> 16) & 0xFF;
+    s[2] = (value >> 8) & 0xFF;
+    s[3] = value & 0xFF;
+    return sizeof(uint16_t);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_t len)
+{
+    int pos;
+
+    pos = 0;
+    unpack_16(data, 0xFFA8);
+    pos += 2;
+
+    span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX0\n");
+    unpack_16(&data[pos], 0xFFE1);
+    pos += 2;
+    unpack_16(&data[pos], 2 + 6 + 10);
+    pos += 2;
+    memcpy(&data[pos], "G3FAX\0", 6);
+    pos += 6;
+    unpack_16(&data[pos], 1997);
+    pos += 2;
+    unpack_16(&data[pos], s->x_resolution);
+    pos += 2;
+    /* JBIG coding method (0) is the only possible value here */
+    data[pos] = 0;
+    pos += 1;
+    data[pos] = 42; //image_type;
+    pos += 1;
+    data[pos] = s->bit_planes[0];
+    pos += 1;
+    data[pos] = s->bit_planes[1];
+    pos += 1;
+    data[pos] = s->bit_planes[2];
+    pos += 1;
+    data[pos] = s->bit_planes[3];
+    pos += 1;
+
+    if (s->lab.offset_L != 0
+        ||
+        s->lab.range_L != 100
+        ||
+        s->lab.offset_a != 128
+        ||
+        s->lab.range_a != 170
+        ||
+        s->lab.offset_b != 96
+        ||
+        s->lab.range_b != 200)
+    {
+        span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX1\n");
+        unpack_16(&data[pos], 0xFFE1);
+        pos += 2;
+        unpack_16(&data[pos], 2 + 6 + 12);
+        pos += 2;
+        memcpy(&data[pos], "G3FAX\1", 6);
+        pos += 6;
+        unpack_16(&data[pos + 0], s->lab.offset_L);
+        unpack_16(&data[pos + 2], s->lab.range_L);
+        unpack_16(&data[pos + 4], s->lab.offset_a);
+        unpack_16(&data[pos + 6], s->lab.range_a);
+        unpack_16(&data[pos + 8], s->lab.offset_b);
+        unpack_16(&data[pos + 10], s->lab.range_b);
+        pos += 12;
+    }
+
+    if (s->lab.x_n != 0.9638f  ||  s->lab.y_n != 1.0f  ||  s->lab.z_n != 0.8245f)
+    {
+        span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX2\n");
+        unpack_16(&data[pos], 0xFFE1);
+        pos += 2;
+        unpack_16(&data[pos], 2 + 6 + 6);
+        pos += 2;
+        memcpy(&data[pos], "G3FAX\2", 6);
+        pos += 6;
+        unpack_16(&data[pos], 0);
+        unpack_16(&data[pos + 2], 0);
+        unpack_16(&data[pos + 4], 0);
+        set_illuminant_from_code(&s->logging, &s->lab, &data[pos]);
+        pos += 6;
+    }
+
+#if 0
+    if (s->colour_map)
+    {
+        span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX3\n");
+        unpack_16(&data[pos], 0xFFE3);
+        pos += 2;
+        unpack_32(&data[pos], ???);
+        pos += 4;
+        memcpy(&data[pos], "G3FAX\3", 6);
+        pos += 6;
+        unpack_16(&data[pos], table_id);
+        pos += 2;
+        unpack_32(&data[pos], s->colour_map_entries);
+        pos += 4;
+        srgb_to_lab(&s->lab, &data[pos], s->colour_map, s->colour_map_entries);
+        pos += 3*s->colour_map_entries;
+    }
+#endif
+
+    span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX-FF\n");
+    unpack_16(&data[pos], 0xFFE1);
+    pos += 2;
+    unpack_16(&data[pos], 2 + 6);
+    pos += 2;
+    memcpy(&data[pos], "G3FAX\xFF", 6);
+    pos += 6;
+    return pos;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) t43_encode_set_options(t43_encode_state_t *s,
+                                          uint32_t l0,
+                                          int mx,
+                                          int options)
+{
+    t85_encode_set_options(&s->t85, l0, mx, options);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_set_image_width(t43_encode_state_t *s, uint32_t image_width)
+{
+    return t85_encode_set_image_width(&s->t85, image_width);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_set_image_length(t43_encode_state_t *s, uint32_t image_length)
+{
+    return t85_encode_set_image_length(&s->t85, image_length);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s)
+{
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) t43_encode_comment(t43_encode_state_t *s, const uint8_t comment[], size_t len)
+{
+    t85_encode_comment(&s->t85, comment, len);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_image_complete(t43_encode_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_get(t43_encode_state_t *s, uint8_t buf[], size_t max_len)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(uint32_t) t43_encode_get_image_width(t43_encode_state_t *s)
+{
+    return t85_encode_get_image_width(&s->t85);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(uint32_t) t43_encode_get_image_length(t43_encode_state_t *s)
+{
+    return t85_encode_get_image_length(&s->t85);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_get_compressed_image_size(t43_encode_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_set_row_read_handler(t43_encode_state_t *s,
+                                                  t4_row_read_handler_t handler,
+                                                  void *user_data)
+{
+    s->row_read_handler = handler;
+    s->row_read_user_data = user_data;
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(logging_state_t *) t43_encode_get_logging_state(t43_encode_state_t *s)
+{
+    return &s->logging;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_restart(t43_encode_state_t *s, uint32_t image_width, uint32_t image_length)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(t43_encode_state_t *) t43_encode_init(t43_encode_state_t *s,
+                                                   uint32_t image_width,
+                                                   uint32_t image_length,
+                                                   t4_row_read_handler_t handler,
+                                                   void *user_data)
+{
+    if (s == NULL)
+    {
+        if ((s = (t43_encode_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    memset(s, 0, sizeof(*s));
+    span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
+    span_log_set_protocol(&s->logging, "T.43");
+
+    s->row_read_handler = handler;
+    s->row_read_user_data = user_data;
+
+    t85_encode_init(&s->t85,
+                    image_width,
+                    image_length,
+                    handler,
+                    user_data);
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_release(t43_encode_state_t *s)
+{
+    t85_encode_release(&s->t85);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_encode_free(t43_encode_state_t *s)
+{
+    int ret;
+
+    t85_encode_free(&s->t85);
+    ret = t43_encode_release(s);
+    free(s);
+    return ret;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) t43_decode_rx_status(t43_decode_state_t *s, int status)
+{
+    span_log(&s->logging, SPAN_LOG_FLOW, "Signal status is %s (%d)\n", signal_status_to_str(status), status);
+    switch (status)
+    {
+    case SIG_STATUS_TRAINING_IN_PROGRESS:
+    case SIG_STATUS_TRAINING_FAILED:
+    case SIG_STATUS_TRAINING_SUCCEEDED:
+    case SIG_STATUS_CARRIER_UP:
+        /* Ignore these */
+        break;
+    case SIG_STATUS_CARRIER_DOWN:
+    case SIG_STATUS_END_OF_DATA:
+        /* Finalise the image */
+        t85_decode_put(&s->t85, NULL, 0);
+        break;
+    default:
+        span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected rx status - %d!\n", status);
+        break;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+static void set_simple_colour_map(t43_decode_state_t *s, int code)
+{
+    switch (code)
+    {
+    case 0:
+        /* Table 3/T.43 1 bit/colour image (using RGB primaries) */
+        memset(s->colour_map, 0, sizeof(s->colour_map));
+        /* Black */
+        /* Blue */
+        s->colour_map[3*0x20 + 2] = 0xF0;
+        /* Green */
+        s->colour_map[3*0x40 + 1] = 0xF0;
+        /* Green + Blue */
+        s->colour_map[3*0x60 + 1] = 0xF0;
+        s->colour_map[3*0x60 + 2] = 0xF0;
+        /* Red */
+        s->colour_map[3*0x80 + 0] = 0xF0;
+        /* Red + Blue */
+        s->colour_map[3*0xA0 + 0] = 0xF0;
+        s->colour_map[3*0xA0 + 2] = 0xF0;
+        /* Red + Green */
+        s->colour_map[3*0xC0 + 0] = 0xF0;
+        s->colour_map[3*0xC0 + 1] = 0xF0;
+        /* White */
+        s->colour_map[3*0xE0 + 0] = 0xF0;
+        s->colour_map[3*0xE0 + 1] = 0xF0;
+        s->colour_map[3*0xE0 + 2] = 0xF0;
+        s->colour_map_entries = 256;
+        break;
+    case 1:
+        /* Table 2/T.43 1 bit/colour image (using CMY primaries) */
+        memset(s->colour_map, 0, sizeof(s->colour_map));
+        /* White */
+        s->colour_map[3*0x00 + 0] = 0xF0;
+        s->colour_map[3*0x00 + 1] = 0xF0;
+        s->colour_map[3*0x00 + 2] = 0xF0;
+        /* Yellow */
+        s->colour_map[3*0x20 + 0] = 0xF0;
+        s->colour_map[3*0x20 + 1] = 0xF0;
+        /* Magenta */
+        s->colour_map[3*0x40 + 0] = 0xF0;
+        s->colour_map[3*0x40 + 2] = 0xF0;
+        /* Magenta + Yellow */
+        s->colour_map[3*0x60 + 0] = 0xF0;
+        /* Cyan */
+        s->colour_map[3*0x80 + 1] = 0xF0;
+        /* Cyan + Yellow */
+        s->colour_map[3*0xA0 + 1] = 0xF0;
+        /* Cyan + Magenta */
+        s->colour_map[3*0xC0 + 2] = 0xF0;
+        /* Black */
+        s->colour_map_entries = 256;
+        break;
+    case 2:
+        /* Table 1/T.43 1 bit/colour image (using CMYK primaries) */
+        memset(s->colour_map, 0, sizeof(s->colour_map));
+        /* White */
+        s->colour_map[3*0x00 + 0] = 0xF0;
+        s->colour_map[3*0x00 + 1] = 0xF0;
+        s->colour_map[3*0x00 + 2] = 0xF0;
+        /* Yellow */
+        s->colour_map[3*0x20 + 0] = 0xF0;
+        s->colour_map[3*0x20 + 1] = 0xF0;
+        /* Magenta */
+        s->colour_map[3*0x40 + 0] = 0xF0;
+        s->colour_map[3*0x40 + 2] = 0xF0;
+        /* Magenta + Yellow */
+        s->colour_map[3*0x60 + 0] = 0xF0;
+        /* Cyan */
+        s->colour_map[3*0x80 + 1] = 0xF0;
+        /* Cyan + Yellow */
+        s->colour_map[3*0xA0 + 1] = 0xF0;
+        /* Cyan + Magenta */
+        s->colour_map[3*0xC0 + 2] = 0xF0;
+        /* Black */
+        s->colour_map_entries = 256;
+        break;
+    case 16:
+        /* Palettized colour image (using CIELAB 8 bits/component precision table) */
+        break;
+    case 17:
+        /* Palettized colour image (using CIELAB 12 bits/component precision table) */
+        break;
+    case 32:
+        /* Gray-scale image (using L*) */
+        break;
+    case 48:
+        /* Continuous-tone colour image (using CIELAB) */
+        break;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int t43_analyse_header(t43_decode_state_t *s, const uint8_t data[], size_t len)
+{
+    int seg;
+    int pos;
+    int table_id;
+    int val[6];
+    uint8_t col[3];
+    int i;
+
+    /* Set defaults */
+    set_lab_illuminant(&s->lab, 0.9638f, 1.0f, 0.8245f);
+    set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, FALSE);
+    pos = 0;
+    if (pack_16(&data[pos]) != 0xFFA8)
+        return 0;
+    span_log(&s->logging, SPAN_LOG_FLOW, "Got BCIH (bit-plane colour image header)\n");
+    pos += 2;
+    for (;;)
+    {
+        if (pack_16(&data[pos]) == 0xFFE1)
+        {
+            pos += 2;
+            seg = pack_16(&data[pos]);
+            pos += 2;
+            seg -= 2;
+            if (seg >= 6  &&  strncmp((char *) &data[pos], "G3FAX", 5) == 0)
+            {
+                if (data[pos + 5] == 0xFF)
+                {
+                    span_log(&s->logging, SPAN_LOG_FLOW, "Got ECIH (end of colour image header)\n");
+                    if (seg != 6)
+                        span_log(&s->logging, SPAN_LOG_FLOW, "Got bad ECIH length - %d\n", seg);
+                    pos += seg;
+                    break;
+                }
+                switch (data[pos + 5])
+                {
+                case 0:
+                    span_log(&s->logging, SPAN_LOG_FLOW, "Got G3FAX0\n");
+                    if (seg >= 6 + 10)
+                    {
+                        val[0] = pack_16(&data[pos + 6 + 0]);
+                        s->x_resolution = pack_16(&data[pos + 6 + 2]);
+                        val[2] = data[pos + 6 + 4];
+                        val[3] = data[pos + 6 + 5];
+                        s->bit_planes[0] = data[pos + 6 + 6];
+                        s->bit_planes[1] = data[pos + 6 + 7];
+                        s->bit_planes[2] = data[pos + 6 + 8];
+                        s->bit_planes[3] = data[pos + 6 + 9];
+                        span_log(&s->logging,
+                                 SPAN_LOG_FLOW,
+                                 "Version %d, resolution %.2fdpi, coding method %d, type %s (%d), bit planes %d,%d,%d,%d\n",
+                                 val[0],
+                                 s->x_resolution/100.0f,
+                                 val[2],
+                                 t43_image_type_to_str(val[3]),
+                                 val[3],
+                                 s->bit_planes[0],
+                                 s->bit_planes[1],
+                                 s->bit_planes[2],
+                                 s->bit_planes[3]);
+                        set_simple_colour_map(s, val[3]);
+                    }
+                    else
+                    {
+                        span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX0 length - %d\n", seg);
+                    }
+                    break;
+                case 1:
+                    span_log(&s->logging, SPAN_LOG_FLOW, "Set gamut\n");
+                    if (seg >= 6 + 12)
+                        set_gamut_from_code(&s->logging, &s->lab, &data[pos + 6]);
+                    else
+                        span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX1 length - %d\n", seg);
+                    break;
+                case 2:
+                    span_log(&s->logging, SPAN_LOG_FLOW, "Set illuminant\n");
+                    if (seg >= 6 + 4)
+                        set_illuminant_from_code(&s->logging, &s->lab, &data[pos + 6]);
+                    else
+                        span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX2 length - %d\n", seg);
+                    break;
+                default:
+                    span_log(&s->logging, SPAN_LOG_FLOW, "Got unexpected G3FAX%d length - %d\n", data[pos + 5], seg);
+                    break;
+                }
+            }
+            pos += seg;
+        }
+        else if (pack_16(&data[pos]) == 0xFFE3)
+        {
+            pos += 2;
+            seg = pack_32(&data[pos]);
+            pos += 4;
+            seg -= 4;
+            if (seg >= 6)
+            {
+                if (strncmp((char *) &data[pos], "G3FAX\3", 6) == 0)
+                {
+                    span_log(&s->logging, SPAN_LOG_FLOW, "Got G3FAX3\n");
+                    table_id = pack_16(&data[pos + 6]);
+                    span_log(&s->logging, SPAN_LOG_FLOW, "  Table ID %3d\n", table_id);
+                    switch (table_id)
+                    {
+                    case 0:
+                        /* 8 bit CIELAB */
+                        s->colour_map_entries = pack_32(&data[pos + 8]);
+                        span_log(&s->logging, SPAN_LOG_FLOW, "  Entries %6d\n", s->colour_map_entries);
+                        if (seg >= 12 + s->colour_map_entries*3)
+                        {
+                            lab_to_srgb(&s->lab, s->colour_map, &data[pos + 12], s->colour_map_entries);
+                        }
+                        else
+                        {
+                            span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX3 length - %d\n", seg);
+                        }
+                        break;
+                    case 4:
+                        /* 12 bit CIELAB */
+                        s->colour_map_entries = pack_32(&data[pos + 8]);
+                        span_log(&s->logging, SPAN_LOG_FLOW, "  Entries %6d\n", s->colour_map_entries);
+                        /* TODO: implement 12bit stuff */
+                        if (seg >= 12 + s->colour_map_entries*3*2)
+                        {
+                            for (i = 0;  i < s->colour_map_entries;  i++)
+                            {
+                                col[0] = pack_16(&data[pos + 12 + 6*i]) >> 4;
+                                col[1] = pack_16(&data[pos + 12 + 6*i + 2]) >> 4;
+                                col[2] = pack_16(&data[pos + 12 + 6*i + 4]) >> 4;
+                                lab_to_srgb(&s->lab, &s->colour_map[3*i], col, 1);
+                            }
+                        }
+                        else
+                        {
+                            span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX3 length - %d\n", seg);
+                        }
+                        break;
+                    default:
+                        span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX3 table ID - %d\n", table_id);
+                        break;
+                    }
+                }
+            }
+            pos += seg;
+        }
+        else
+        {
+            break;
+        }
+    }
+    return pos;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int t85_row_write_handler(void *user_data, const uint8_t buf[], size_t len)
+{
+    t43_decode_state_t *s;
+    int i;
+    int j;
+    int image_size;
+    uint8_t mask;
+
+    /* Repack the bit packed T.85 image plane to a 3 x 8 bits per pixel colour image.
+       We use the red entry now. This will be remapped to RGB later, as we apply the
+       colour map. */
+    s = (t43_decode_state_t *) user_data;
+
+    if (s->buf == NULL)
+    {
+        image_size = 3*s->t85.xd*s->t85.yd;
+        if ((s->buf = malloc(image_size)) == NULL)
+            return -1;
+        memset(s->buf, 0, image_size);
+    }
+
+    for (i = 0;  i < len;  i++)
+    {
+        mask = 0x80;
+        for (j = 0;  j < 24;  j += 3)
+        {
+            if ((buf[i] & mask))
+                s->buf[s->ptr + j] |= s->bit_plane_mask;
+            mask >>= 1;
+        }
+        s->ptr += 3*8;
+    }
+    s->row++;
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_put(t43_decode_state_t *s, const uint8_t data[], size_t len)
+{
+    int i;
+    int j;
+    int plane_len;
+    int total_len;
+    int result;
+
+    /* TODO: this isn't allowing for the header arriving in chunks */
+    if (s->current_bit_plane < 0)
+    {
+        i = t43_analyse_header(s, data, len);
+        data += i;
+        len -= i;
+        s->bit_plane_mask = 0x80;
+        s->current_bit_plane++;
+
+        /* There must be at least one bit plane. The real value for this will
+           be filled in as the first plane is processed */
+        s->t85.bit_planes = 1;
+        s->ptr = 0;
+        s->row = 0;
+        s->buf = NULL;
+        s->plane_ptr = 0;
+        t85_decode_new_plane(&s->t85);
+    }
+
+    /* Now deal the bit-planes, one after another. */
+    while (s->current_bit_plane < s->t85.bit_planes)
+    {
+        j = s->current_bit_plane;
+
+        result = t85_decode_put(&s->t85, data, len);
+        if (result != T4_DECODE_OK)
+        {
+            s->plane_ptr += len;
+            return result;
+        }
+        plane_len = t85_decode_get_compressed_image_size(&s->t85);
+        data += (plane_len/8 - s->plane_ptr);
+        len -= (plane_len/8 - s->plane_ptr);
+        total_len = s->ptr;
+
+        /* Start the next plane */
+        s->bit_plane_mask >>= 1;
+        s->current_bit_plane++;
+        s->ptr = 0;
+        s->row = 0;
+        s->plane_ptr = 0;
+        t85_decode_new_plane(&s->t85);
+    }
+    /* Apply the colour map, and produce the RGB data from the collected bit-planes */
+    for (j = 0;  j < total_len;  j += 3)
+    {
+        i = s->buf[j];
+        s->buf[j] = s->colour_map[3*i];
+        s->buf[j + 1] = s->colour_map[3*i + 1];
+        s->buf[j + 2] = s->colour_map[3*i + 2];
+    }
+    for (j = 0;  j < s->t85.yd;  j++)
+    {
+        s->row_write_handler(s->row_write_user_data, &s->buf[j*3*s->t85.xd], 3*s->t85.xd);
+    }
+    return result;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_set_row_write_handler(t43_decode_state_t *s,
+                                                   t4_row_write_handler_t handler,
+                                                   void *user_data)
+{
+    s->row_write_handler = handler;
+    s->row_write_user_data = user_data;
+    s->t85.row_write_handler = handler;
+    s->t85.row_write_user_data = user_data;
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_set_comment_handler(t43_decode_state_t *s,
+                                                 uint32_t max_comment_len,
+                                                 t4_row_write_handler_t handler,
+                                                 void *user_data)
+{
+    return t85_decode_set_comment_handler(&s->t85, max_comment_len, handler, user_data);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_set_image_size_constraints(t43_decode_state_t *s,
+                                                        uint32_t max_xd,
+                                                        uint32_t max_yd)
+{
+    return t85_decode_set_image_size_constraints(&s->t85, max_xd, max_yd);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(uint32_t) t43_decode_get_image_width(t43_decode_state_t *s)
+{
+    return t85_decode_get_image_width(&s->t85);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(uint32_t) t43_decode_get_image_length(t43_decode_state_t *s)
+{
+    return t85_decode_get_image_length(&s->t85);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_get_compressed_image_size(t43_decode_state_t *s)
+{
+    return t85_decode_get_compressed_image_size(&s->t85);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(logging_state_t *) t43_decode_get_logging_state(t43_decode_state_t *s)
+{
+    return &s->logging;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s)
+{
+    return t85_decode_restart(&s->t85);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s,
+                                                   t4_row_write_handler_t handler,
+                                                   void *user_data)
+{
+    if (s == NULL)
+    {
+        if ((s = (t43_decode_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    memset(s, 0, sizeof(*s));
+    span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
+    span_log_set_protocol(&s->logging, "T.43");
+
+    s->row_write_handler = handler;
+    s->row_write_user_data = user_data;
+
+    t85_decode_init(&s->t85, t85_row_write_handler, s);
+
+    s->t85.min_bit_planes = 1;
+    s->t85.max_bit_planes = 8;
+    s->bit_plane_mask = 0x80;
+    s->current_bit_plane = -1;
+
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_release(t43_decode_state_t *s)
+{
+    t85_decode_release(&s->t85);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t43_decode_free(t43_decode_state_t *s)
+{
+    int ret;
+
+    ret = t43_decode_release(s);
+    t85_decode_free(&s->t85);
+    free(s);
+    return ret;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
index 2c5d6971adbcb2b5f8813a02689c55c56d7536af..9d7dc0a6e468e07fa73f6a8c4756ef36a97d21fd 100644 (file)
@@ -107,6 +107,8 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding)
         return "T.85";
     case T4_COMPRESSION_T85_L0:
         return "T.85(L0)";
+    case T4_COMPRESSION_T88:
+        return "T.88";
     case T4_COMPRESSION_T42_T81:
         return "T.81";
     case T4_COMPRESSION_SYCC_T81:
index 6ad6821b9bbe26dab1272e1d2b89d652304e026d..07903816bde7e363b4bca51f9cf4d81b357f8e80 100644 (file)
@@ -104,12 +104,12 @@ static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length);
 
 static const res_table_t x_res_table[] =
 {
-    //{ 100.0f/CM_PER_INCH, T4_X_RESOLUTION_100},
+    { 100.0f/CM_PER_INCH, T4_X_RESOLUTION_100},
     { 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4},
-    //{ 200.0f/CM_PER_INCH, T4_X_RESOLUTION_200},
+    { 200.0f/CM_PER_INCH, T4_X_RESOLUTION_200},
     { 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8},
     { 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300},
-    //{ 400.0f/CM_PER_INCH, T4_X_RESOLUTION_400},
+    { 400.0f/CM_PER_INCH, T4_X_RESOLUTION_400},
     { 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16},
     { 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600},
     { 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800},
@@ -120,12 +120,12 @@ static const res_table_t x_res_table[] =
 static const res_table_t y_res_table[] =
 {
     {             38.50f, T4_Y_RESOLUTION_STANDARD},
-    //{ 100.0f/CM_PER_INCH, T4_Y_RESOLUTION_100},
+    { 100.0f/CM_PER_INCH, T4_Y_RESOLUTION_100},
     {             77.00f, T4_Y_RESOLUTION_FINE},
-    //{ 200.0f/CM_PER_INCH, T4_Y_RESOLUTION_200},
+    { 200.0f/CM_PER_INCH, T4_Y_RESOLUTION_200},
     { 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300},
     {            154.00f, T4_Y_RESOLUTION_SUPERFINE},
-    //{ 400.0f/CM_PER_INCH, T4_Y_RESOLUTION_400},
+    { 400.0f/CM_PER_INCH, T4_Y_RESOLUTION_400},
     { 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600},
     { 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800},
     {1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200},
@@ -385,7 +385,7 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
         best_y_entry = 0;
     s->metadata.y_resolution = y_res_table[best_y_entry].code;
 
-    //s->metadata.resolution_code = resolution_map[best_y_entry][best_x_entry];
+    s->metadata.resolution_code = resolution_map[best_y_entry][best_x_entry];
 
     t4_tx_set_image_width(s, s->image_width);
     t4_tx_set_image_length(s, s->image_length);
index 9aae8bfbf1d5c4c06c91f39a46314972e538d40c..b88e2205b69d007c8b32b5cfd88eef248ed29d92 100644 (file)
 #define FP_SCALE(x)                     (x)
 #endif
 
-#include "v17_v32bis_rx_rrc.h"
+#if defined(SPANDSP_USE_FIXED_POINTx)
+#define FP_SYNC_SCALE(x)                FP_Q_6_10(x)
+#define FP_SYNC_SCALE_32(x)             FP_Q_6_10_32(x)
+#define FP_SYNC_SHIFT_FACTOR            10
+#else
+#define FP_SYNC_SCALE(x)                (x)
+#define FP_SYNC_SCALE_32(x)             (x)
+#endif
 
 #define FP_CONSTELLATION_SCALE(x)       FP_SCALE(x)
+#if defined(SPANDSP_USE_FIXED_POINT)
+#define FP_CONSTELLATION_SHIFT_FACTOR   FP_SHIFT_FACTOR
+#endif
 
+#include "v17_v32bis_rx_rrc.h"
 #include "v17_v32bis_tx_constellation_maps.h"
 #include "v17_v32bis_rx_constellation_maps.h"
 
 /*! The 16 bit pattern used in the bridge section of the training sequence */
 #define V17_BRIDGE_WORD                 0x8880
 
+/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
+/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
+/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
+#define SIN_LOW_BAND_EDGE               0.453990499f
+#define COS_LOW_BAND_EDGE               0.891006542f
+#define SIN_HIGH_BAND_EDGE              0.707106781f
+#define COS_HIGH_BAND_EDGE             -0.707106781f
+#define ALPHA                           0.99f
+
+#define SYNC_LOW_BAND_EDGE_COEFF_0      FP_SYNC_SCALE(2.0f*ALPHA*COS_LOW_BAND_EDGE)
+#define SYNC_LOW_BAND_EDGE_COEFF_1      FP_SYNC_SCALE(-ALPHA*ALPHA)
+#define SYNC_LOW_BAND_EDGE_COEFF_2      FP_SYNC_SCALE(-ALPHA*SIN_LOW_BAND_EDGE)
+#define SYNC_HIGH_BAND_EDGE_COEFF_0     FP_SYNC_SCALE(2.0f*ALPHA*COS_HIGH_BAND_EDGE)
+#define SYNC_HIGH_BAND_EDGE_COEFF_1     FP_SYNC_SCALE(-ALPHA*ALPHA)
+#define SYNC_HIGH_BAND_EDGE_COEFF_2     FP_SYNC_SCALE(-ALPHA*SIN_HIGH_BAND_EDGE)
+#define SYNC_MIXED_EDGES_COEFF_3        FP_SYNC_SCALE(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE))
+
 enum
 {
     TRAINING_STAGE_NORMAL_OPERATION = 0,
@@ -123,33 +151,6 @@ enum
     TRAINING_STAGE_PARKED
 };
 
-/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
-/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
-/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
-#define SIN_LOW_BAND_EDGE               0.453990499f
-#define COS_LOW_BAND_EDGE               0.891006542f
-#define SIN_HIGH_BAND_EDGE              0.707106781f
-#define COS_HIGH_BAND_EDGE             -0.707106781f
-#define ALPHA                           0.99f
-
-#if defined(SPANDSP_USE_FIXED_POINTx)
-#define SYNC_LOW_BAND_EDGE_COEFF_0      FP_Q_6_10(2.0f*ALPHA*COS_LOW_BAND_EDGE)
-#define SYNC_LOW_BAND_EDGE_COEFF_1      FP_Q_6_10(-ALPHA*ALPHA)
-#define SYNC_LOW_BAND_EDGE_COEFF_2      FP_Q_6_10(-ALPHA*SIN_LOW_BAND_EDGE)
-#define SYNC_HIGH_BAND_EDGE_COEFF_0     FP_Q_6_10(2.0f*ALPHA*COS_HIGH_BAND_EDGE)
-#define SYNC_HIGH_BAND_EDGE_COEFF_1     FP_Q_6_10(-ALPHA*ALPHA)
-#define SYNC_HIGH_BAND_EDGE_COEFF_2     FP_Q_6_10(-ALPHA*SIN_HIGH_BAND_EDGE)
-#define SYNC_MIXED_EDGES_COEFF_3        FP_Q_6_10(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE))
-#else
-#define SYNC_LOW_BAND_EDGE_COEFF_0      (2.0f*ALPHA*COS_LOW_BAND_EDGE)
-#define SYNC_LOW_BAND_EDGE_COEFF_1      (-ALPHA*ALPHA)
-#define SYNC_LOW_BAND_EDGE_COEFF_2      (-ALPHA*SIN_LOW_BAND_EDGE)
-#define SYNC_HIGH_BAND_EDGE_COEFF_0     (2.0f*ALPHA*COS_HIGH_BAND_EDGE)
-#define SYNC_HIGH_BAND_EDGE_COEFF_1     (-ALPHA*ALPHA)
-#define SYNC_HIGH_BAND_EDGE_COEFF_2     (-ALPHA*SIN_HIGH_BAND_EDGE)
-#define SYNC_MIXED_EDGES_COEFF_3        (-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE))
-#endif
-
 #if defined(SPANDSP_USE_FIXED_POINTx)
 static const int16_t constellation_spacing[4] =
 #else
@@ -245,14 +246,14 @@ static void equalizer_reset(v17_rx_state_t *s)
 {
     /* Start with an equalizer based on everything being perfect */
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    static const complexi16_t x = {FP_SCALE(3.0f), FP_SCALE(0.0f)};
+    static const complexi16_t x = {FP_CONSTELLATION_SCALE(3.0f), FP_CONSTELLATION_SCALE(0.0f)};
 
     cvec_zeroi16(s->eq_coeff, V17_EQUALIZER_LEN);
     s->eq_coeff[V17_EQUALIZER_PRE_LEN] = x;
     cvec_zeroi16(s->eq_buf, V17_EQUALIZER_LEN);
     s->eq_delta = 32768.0f*EQUALIZER_DELTA/V17_EQUALIZER_LEN;
 #else
-    static const complexf_t x = {3.0f, 0.0f};
+    static const complexf_t x = {FP_CONSTELLATION_SCALE(3.0f), FP_CONSTELLATION_SCALE(0.0f)};
 
     cvec_zerof(s->eq_coeff, V17_EQUALIZER_LEN);
     s->eq_coeff[V17_EQUALIZER_PRE_LEN] = x;
@@ -313,20 +314,6 @@ static void tune_equalizer(v17_rx_state_t *s, const complexf_t *z, const complex
 #endif
 /*- End of function --------------------------------------------------------*/
 
-static int descramble(v17_rx_state_t *s, int in_bit)
-{
-    int out_bit;
-
-    out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
-    s->scramble_reg <<= 1;
-    if (s->training_stage > TRAINING_STAGE_NORMAL_OPERATION  &&  s->training_stage < TRAINING_STAGE_TCM_WINDUP)
-        s->scramble_reg |= out_bit;
-    else
-        s->scramble_reg |= (in_bit & 1);
-    return out_bit;
-}
-/*- End of function --------------------------------------------------------*/
-
 #if defined(SPANDSP_USE_FIXED_POINTx)
 static __inline__ void track_carrier(v17_rx_state_t *s, const complexi16_t *z, const complexi16_t *target)
 #else
@@ -355,6 +342,21 @@ static __inline__ void track_carrier(v17_rx_state_t *s, const complexf_t *z, con
 }
 /*- End of function --------------------------------------------------------*/
 
+static int descramble(v17_rx_state_t *s, int in_bit)
+{
+    int out_bit;
+
+    in_bit &= 1;
+    out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
+    s->scramble_reg <<= 1;
+    if (s->training_stage > TRAINING_STAGE_NORMAL_OPERATION  &&  s->training_stage < TRAINING_STAGE_TCM_WINDUP)
+        s->scramble_reg |= out_bit;
+    else
+        s->scramble_reg |= (in_bit & 1);
+    return out_bit;
+}
+/*- End of function --------------------------------------------------------*/
+
 static __inline__ void put_bit(v17_rx_state_t *s, int bit)
 {
     int out_bit;
@@ -675,13 +677,13 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
     complexi16_t z;
     complexi16_t z16;
     const complexi16_t *target;
-    static const complexi16_t zero = {0, 0};
+    static const complexi16_t zero = {FP_SCALE(0.0f), FP_SCALE(0.0f)};
 #else
     float p;
     complexf_t z;
     complexf_t zz;
     const complexf_t *target;
-    static const complexf_t zero = {0.0f, 0.0f};
+    static const complexf_t zero = {FP_SCALE(0.0f), FP_SCALE(0.0f)};
 #endif
     int bit;
     int i;
@@ -724,13 +726,8 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             s->training_stage = TRAINING_STAGE_LOG_PHASE;
             vec_zeroi32(s->diff_angles, 16);
             s->last_angles[0] = arctan2(z.im, z.re);
-#if defined(SPANDSP_USE_FIXED_POINTx)
-            if (s->agc_scaling_save == 0)
+            if (s->agc_scaling_save == FP_SCALE(0.0f))
                 s->agc_scaling_save = s->agc_scaling;
-#else
-            if (s->agc_scaling_save == 0.0f)
-                s->agc_scaling_save = s->agc_scaling;
-#endif
         }
         break;
     case TRAINING_STAGE_LOG_PHASE:
@@ -816,11 +813,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             {
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
                 /* Park this modem */
-#if defined(SPANDSP_USE_FIXED_POINTx)
-                s->agc_scaling_save = 0;
-#else
-                s->agc_scaling_save = 0.0f;
-#endif
+                s->agc_scaling_save = FP_SCALE(0.0f);
                 s->training_stage = TRAINING_STAGE_PARKED;
                 report_status_change(s, SIG_STATUS_TRAINING_FAILED);
                 break;
@@ -860,11 +853,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                of a real training sequence. Note that this might be TEP. */
             span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
             /* Park this modem */
-#if defined(SPANDSP_USE_FIXED_POINTx)
-            s->agc_scaling_save = 0;
-#else
-            s->agc_scaling_save = 0.0f;
-#endif
+            s->agc_scaling_save = FP_SCALE(0.0f);
             s->training_stage = TRAINING_STAGE_PARKED;
             report_status_change(s, SIG_STATUS_TRAINING_FAILED);
         }
@@ -880,12 +869,11 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
 #if defined(SPANDSP_USE_FIXED_POINTx)
         z16 = complex_subi16(&z, target);
         s->training_error += poweri16(&z16);
-        if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000  ||  s->training_error < 1*FP_FACTOR*FP_FACTOR  ||  s->training_error > 200*FP_FACTOR*FP_FACTOR)
 #else
         zz = complex_subf(&z, target);
         s->training_error = powerf(&zz);
-        if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000  ||  s->training_error < 1.0f  ||  s->training_error > 200.0f)
 #endif
+        if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000  ||  s->training_error < FP_SCALE(1.0f)*FP_SCALE(1.0f)  ||  s->training_error > FP_SCALE(200.0f)*FP_SCALE(1.0f))
 #else
         if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000)
 #endif
@@ -948,15 +936,12 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         {
 #if defined(SPANDSP_USE_FIXED_POINTx)
             span_log(&s->logging, SPAN_LOG_FLOW, "Long training error %d\n", s->training_error);
-            if (s->training_error < 20.0f*1.414f*FP_FACTOR*FP_FACTOR*constellation_spacing[s->space_map])
-            {
-                s->training_error = 0;
 #else
             span_log(&s->logging, SPAN_LOG_FLOW, "Long training error %f\n", s->training_error);
-            if (s->training_error < 20.0f*1.414f*constellation_spacing[s->space_map])
-            {
-                s->training_error = 0.0f;
 #endif
+            if (s->training_error < FP_SCALE(20.0f)*FP_SCALE(1.414f)*constellation_spacing[s->space_map])
+            {
+                s->training_error = FP_SCALE(0.0f);
                 s->training_count = 0;
                 s->training_stage = TRAINING_STAGE_BRIDGE;
             }
@@ -964,11 +949,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             {
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (convergence failed)\n");
                 /* Park this modem */
-#if defined(SPANDSP_USE_FIXED_POINTx)
-                s->agc_scaling_save = 0;
-#else
-                s->agc_scaling_save = 0.0f;
-#endif
+                s->agc_scaling_save = FP_SCALE(0.0f);
                 s->training_stage = TRAINING_STAGE_PARKED;
                 report_status_change(s, SIG_STATUS_TRAINING_FAILED);
             }
@@ -980,11 +961,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         target = &z;
         if (++s->training_count >= V17_TRAINING_SEG_3_LEN)
         {
-#if defined(SPANDSP_USE_FIXED_POINTx)
-            s->training_error = 0;
-#else
-            s->training_error = 0.0f;
-#endif
+            s->training_error = FP_SCALE(0.0f);
             s->training_count = 0;
             if (s->bits_per_symbol == 2)
             {
@@ -1012,11 +989,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             bit = descramble(s, 1);
             bit = (bit << 1) | descramble(s, 1);
             target = &cdba[bit];
-#if defined(SPANDSP_USE_FIXED_POINTx)
-            s->training_error = 0;
-#else
-            s->training_error = 0.0f;
-#endif
+            s->training_error = FP_SCALE(0.0f);
             s->training_count = 1;
             s->training_stage = TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST;
             break;
@@ -1066,11 +1039,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             /* TODO: This was increased by a factor of 10 after studying real world failures.
                      However, it is not clear why this is an improvement, If something gives
                      a huge training error, surely it shouldn't decode too well? */
-#if defined(SPANDSP_USE_FIXED_POINTx)
-            if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*4.0f*FP_FACTOR*FP_FACTOR*constellation_spacing[s->space_map])
-#else
-            if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*4.0f*constellation_spacing[s->space_map])
-#endif
+            if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*FP_SCALE(4.0f)*FP_SCALE(1.0f)*constellation_spacing[s->space_map])
             {
                 s->training_count = 0;
                 if (s->bits_per_symbol == 2)
@@ -1078,11 +1047,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                     /* There is no trellis, so go straight to processing decoded data */
                     /* Restart the differential decoder */
                     s->diff = (s->short_train)  ?  0  :  1;
-#if defined(SPANDSP_USE_FIXED_POINTx)
-                    s->training_error = 0;
-#else
-                    s->training_error = 0.0f;
-#endif
+                    s->training_error = FP_SCALE(0.0f);
                     s->training_stage = TRAINING_STAGE_TEST_ONES;
                 }
                 else
@@ -1116,11 +1081,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
 #endif
         if (++s->training_count >= V17_TRAINING_SEG_4A_LEN)
         {
-#if defined(SPANDSP_USE_FIXED_POINTx)
-            s->training_error = 0;
-#else
-            s->training_error = 0.0f;
-#endif
+            s->training_error = FP_SCALE(0.0f);
             s->training_count = 0;
             /* Restart the differential decoder */
             s->diff = (s->short_train)  ?  0  :  1;
@@ -1143,13 +1104,11 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
 #endif
         if (++s->training_count >= V17_TRAINING_SEG_4_LEN)
         {
-#if defined(SPANDSP_USE_FIXED_POINTx)
-            if (s->training_error < V17_TRAINING_SEG_4_LEN*FP_FACTOR*FP_FACTOR*constellation_spacing[s->space_map])
+            if (s->training_error < V17_TRAINING_SEG_4_LEN*FP_SCALE(1.0f)*FP_SCALE(1.0f)*constellation_spacing[s->space_map])
             {
+#if defined(SPANDSP_USE_FIXED_POINTx)
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded at %dbps (constellation mismatch %d)\n", s->bit_rate, s->training_error);
 #else
-            if (s->training_error < V17_TRAINING_SEG_4_LEN*constellation_spacing[s->space_map])
-            {
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded at %dbps (constellation mismatch %f)\n", s->bit_rate, s->training_error);
 #endif
                 /* We are up and running */
@@ -1167,13 +1126,11 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                 /* Training has failed. Park this modem. */
 #if defined(SPANDSP_USE_FIXED_POINTx)
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %d)\n", s->training_error);
-                if (!s->short_train)
-                    s->agc_scaling_save = 0;
 #else
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %f)\n", s->training_error);
-                if (!s->short_train)
-                    s->agc_scaling_save = 0.0f;
 #endif
+                if (!s->short_train)
+                    s->agc_scaling_save = FP_SCALE(0.0f);
                 s->training_stage = TRAINING_STAGE_PARKED;
                 report_status_change(s, SIG_STATUS_TRAINING_FAILED);
             }
@@ -1317,11 +1274,15 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
         sample.re = (v*s->agc_scaling) >> 10;
         /* Symbol timing synchronisation band edge filters */
         /* Low Nyquist band edge filter */
-        v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> 10) + ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> 10) + sample.re;
+        v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> 10)
+          + ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> 10)
+          + sample.re;
         s->symbol_sync_low[1] = s->symbol_sync_low[0];
         s->symbol_sync_low[0] = v;
         /* High Nyquist band edge filter */
-        v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> 10) + ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> 10) + sample.re;
+        v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> 10)
+          + ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> 10)
+          + sample.re;
         s->symbol_sync_high[1] = s->symbol_sync_high[0];
         s->symbol_sync_high[0] = v;
 #else
@@ -1342,18 +1303,16 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
         if (s->eq_put_step <= 0)
         {
             /* Only AGC until we have locked down the setting. */
+            if (s->agc_scaling_save == FP_SCALE(0.0f))
 #if defined(SPANDSP_USE_FIXED_POINTx)
-            if (s->agc_scaling_save == 0)
-                s->agc_scaling = saturate16(((int32_t) (1024.0f*FP_FACTOR*2.17f))/fixed_sqrt32(power));
+                s->agc_scaling = saturate16(((int32_t) (FP_SCALE(2.17f)*1024.0f))/fixed_sqrt32(power));
 #else
-            if (s->agc_scaling_save == 0.0f)
-                s->agc_scaling = (1.0f/RX_PULSESHAPER_GAIN)*2.17f/sqrtf(power);
+                s->agc_scaling = (FP_SCALE(2.17f)/RX_PULSESHAPER_GAIN)/sqrtf(power);
 #endif
             /* Pulse shape while still at the carrier frequency, using a quadrature
                pair of filters. This results in a properly bandpass filtered complex
                signal, which can be brought directly to baseband by complex mixing.
                No further filtering, to remove mixer harmonics, is needed. */
-            s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
 #if defined(SPANDSP_USE_FIXED_POINTx)
             v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_im[step], V17_RX_FILTER_STEPS, s->rrc_filter_step) >> 15;
             sample.im = (v*s->agc_scaling) >> 10;
@@ -1367,6 +1326,7 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
             zz.re = sample.re*z.re - sample.im*z.im;
             zz.im = -sample.re*z.im - sample.im*z.re;
 #endif
+            s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
             process_half_baud(s, &zz);
         }
 #if defined(SPANDSP_USE_FIXED_POINT)
@@ -1467,11 +1427,10 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
     s->bit_rate = bit_rate;
 #if defined(SPANDSP_USE_FIXED_POINTx)
     vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
-    s->training_error = 0;
 #else
     vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
-    s->training_error = 0.0f;
 #endif
+    s->training_error = FP_SCALE(0.0f);
     s->rrc_filter_step = 0;
 
     s->diff = 1;
@@ -1486,8 +1445,8 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
 #endif
     if (short_train != 2)
         s->short_train = short_train;
-    memset(s->last_angles, 0, sizeof(s->last_angles));
-    memset(s->diff_angles, 0, sizeof(s->diff_angles));
+    vec_zeroi32(s->last_angles, 2);
+    vec_zeroi32(s->diff_angles, 16);
 
     /* Initialise the TCM decoder parameters. */
     /* The accumulated distance vectors are set so state zero starts
@@ -1525,17 +1484,13 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
     {
         s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
         equalizer_reset(s);
+        s->agc_scaling_save = FP_SCALE(0.0f);
 #if defined(SPANDSP_USE_FIXED_POINTx)
-        s->agc_scaling_save = 0;
-        s->agc_scaling = (float) (1024.0f*FP_FACTOR)*2.17f/735.0f;
-#else
-        s->agc_scaling_save = 0.0f;
-        s->agc_scaling = (1.0f/RX_PULSESHAPER_GAIN)*2.17f/735.0f;
-#endif
-#if defined(SPANDSP_USE_FIXED_POINTx)
+        s->agc_scaling = (float) (FP_SCALE(2.17f)*1024.0f)/735.0f;
         s->carrier_track_i = 5000;
         s->carrier_track_p = 40000;
 #else
+        s->agc_scaling = (FP_SCALE(2.17f)/RX_PULSESHAPER_GAIN)/735.0f;
         s->carrier_track_i = 5000.0f;
         s->carrier_track_p = 40000.0f;
 #endif
@@ -1545,23 +1500,13 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
     span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
 
     /* Initialise the working data for symbol timing synchronisation */
-#if defined(SPANDSP_USE_FIXED_POINTx)
     for (i = 0;  i < 2;  i++)
     {
-        s->symbol_sync_low[i] = 0;
-        s->symbol_sync_high[i] = 0;
-        s->symbol_sync_dc_filter[i] = 0;
+        s->symbol_sync_low[i] = FP_SCALE(0.0f);
+        s->symbol_sync_high[i] = FP_SCALE(0.0f);
+        s->symbol_sync_dc_filter[i] = FP_SCALE(0.0f);
     }
-    s->baud_phase = 0;
-#else
-    for (i = 0;  i < 2;  i++)
-    {
-        s->symbol_sync_low[i] = 0.0f;
-        s->symbol_sync_high[i] = 0.0f;
-        s->symbol_sync_dc_filter[i] = 0.0f;
-    }
-    s->baud_phase = 0.0f;
-#endif
+    s->baud_phase = FP_SCALE(0.0f);
     s->baud_half = 0;
 
     s->total_baud_timing_correction = 0;
index 67807bcc85633e11b6951fb302de7dd9e382a7ab..e743d943e8545aaa0396b330d29dd5f5380fb70a 100644 (file)
@@ -861,24 +861,15 @@ int main(int argc, char *argv[])
                                             | T4_SUPPORT_RESOLUTION_600_1200
                                             | T4_SUPPORT_RESOLUTION_1200_1200);
         t30_set_supported_colour_resolutions(t30_state[i], 0);
-        //t30_set_rx_encoding(t30_state[i], T4_COMPRESSION_T85);
+        //t30_set_rx_encoding(t30_state[i], T4_COMPRESSION_T6);
         t30_set_ecm_capability(t30_state[i], use_ecm);
-        if (use_ecm)
-        {
-            t30_set_supported_compressions(t30_state[i],
-                                           T30_SUPPORT_COMPRESSION_T4_1D
-                                         | T30_SUPPORT_COMPRESSION_T4_2D
-                                         | T30_SUPPORT_COMPRESSION_T6
-                                         //| T30_SUPPORT_COMPRESSION_T81
-                                         | T30_SUPPORT_COMPRESSION_T85
-                                         | T30_SUPPORT_COMPRESSION_T85_L0);
-        }
-        else
-        {
-            t30_set_supported_compressions(t30_state[i],
-                                           T30_SUPPORT_COMPRESSION_T4_1D
-                                         | T30_SUPPORT_COMPRESSION_T4_2D);
-        }
+        t30_set_supported_compressions(t30_state[i],
+                                       T4_SUPPORT_COMPRESSION_T4_1D
+                                     | T4_SUPPORT_COMPRESSION_T4_2D
+                                     | T4_SUPPORT_COMPRESSION_T6
+                                     //| T4_SUPPORT_COMPRESSION_t42_T81
+                                     | T4_SUPPORT_COMPRESSION_T85
+                                     | T4_SUPPORT_COMPRESSION_T85_L0);
         t30_set_minimum_scan_line_time(t30_state[i], scan_line_time);
 
         if (mode[i] == T38_GATEWAY_FAX)
@@ -954,6 +945,10 @@ int main(int argc, char *argv[])
                 logging = fax_get_logging_state(fax_state[i]);
                 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
 
+#if 0
+                /* Mute the signal */
+                vec_zeroi16(fax_rx_buf[i], SAMPLES_PER_CHUNK);
+#endif
                 fax_rx(fax_state[i], fax_rx_buf[i], SAMPLES_PER_CHUNK);
                 if (!t30_call_active(t30_state[i]))
                 {
index 6967ee1a6720c25d919282663fa335cf6c93a20a..a002aa73bcd6acf2441b5794c9def227f44196b7 100644 (file)
@@ -106,9 +106,9 @@ static const struct command_response_s fax_send_test_seq[] =
     EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
     //<DIS frame data>
 #if 1
-    RESPONSE("\xFF\x13\x80\x00\xEE\xF8\x80\x80\x91\x80\x80\x80\x18\x78\x57\x10\x03"),   // For audio FAXing
+    RESPONSE("\xFF\x13\x80\x00\xEE\xF8\x80\x80\x89\x80\x80\x80\x18\x18\xB9\x10\x03"),   // For audio FAXing
 #else
-    RESPONSE("\xFF\x13\x80\x04\xEE\xF8\x80\x80\x91\x80\x80\x80\x18\xE4\xE7\x10\x03"),   // For T.38 FAXing
+    RESPONSE("\xFF\x13\x80\x04\xEE\xF8\x80\x80\x89\x80\x80\x80\x18\x84\x09\x10\x03"),   // For T.38 FAXing
 #endif
     RESPONSE("\r\nOK\r\n"),
     //EXCHANGE("AT+FRH=3\r", "\r\nNO CARRIER\r\n"),
@@ -870,7 +870,7 @@ static int t30_tests(int t38_mode, int use_gui, int log_audio, int test_sending,
     if (!done  ||  !sequence_terminated)
     {
         printf("Tests failed\n");
-        return 2;
+        return -1;
     }
 
     return 0;
@@ -934,7 +934,8 @@ int main(int argc, char *argv[])
         }
     }
 
-    t30_tests(t38_mode, use_gui, log_audio, test_sending, g1050_model_no, g1050_speed_pattern_no);
+    if (t30_tests(t38_mode, use_gui, log_audio, test_sending, g1050_model_no, g1050_speed_pattern_no) < 0)
+        return 2;
     printf("Tests passed\n");
     return 0;
 }
index 8e7d10d253117bee7c1e32bb009b0710a02d8760..47716ca7bfcb781c38a21f13e93fcc6eb3c642f8 100644 (file)
@@ -440,7 +440,7 @@ int main(int argc, char *argv[])
         t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
         t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
         t30_set_ecm_capability(t30, use_ecm);
-        t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6 | T30_SUPPORT_COMPRESSION_T85);
+        t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6 | T4_SUPPORT_COMPRESSION_T85);
 
         if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_terminal_timing_update, process_packet, NULL))
             exit(2);
@@ -497,7 +497,7 @@ int main(int argc, char *argv[])
         t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
         t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
         t30_set_ecm_capability(t30, use_ecm);
-        t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6);
+        t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6);
 
         logging = fax_get_logging_state(fax_state);
         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
index ddd5438197ab0a2ed92692acdbfa4a8dfe5875f0..712c80242b9de06658c3d16376766d5b71e6561b 100644 (file)
@@ -47,7 +47,6 @@
 #include <tif_dir.h>
 #endif
 
-//#define IN_FILE_NAME    "../test-data/itu/t24/F21_200.TIF"
 #define IN_FILE_NAME    "../test-data/itu/t24/F21B400.TIF"
 #define OUT_FILE_NAME   "t42_tests_receive.tif"
 
index 37425ec71520752ee87a0babb88a23946333c950..74f397d81926e8aa64e067c3d2db844e284b875e 100644 (file)
@@ -409,7 +409,7 @@ static void fax_prepare(void)
                                         | T4_SUPPORT_RESOLUTION_1200_1200);
     t30_set_supported_colour_resolutions(t30, 0);
     t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
-    t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6);
+    t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6);
     t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
     t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
     t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
@@ -882,7 +882,7 @@ static int next_step(faxtester_state_t *s)
             t30 = fax_get_t30_state(fax);
             t30_set_rx_file(t30, output_tiff_file_name, -1);
             /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
-            t30_set_rx_encoding(t30, T4_COMPRESSION_T4_1D);
+            t30_set_supported_output_compressions(t30, T4_COMPRESSION_T4_1D);
             if (value)
             {
                 sprintf(path, "%s/%s", image_path, (const char *) value);
@@ -897,7 +897,7 @@ static int next_step(faxtester_state_t *s)
             next_tx_file[0] = '\0';
             t30 = fax_get_t30_state(fax);
             /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
-            t30_set_rx_encoding(t30, T4_COMPRESSION_T4_1D);
+            t30_set_supported_output_compressions(t30, T4_COMPRESSION_T4_1D);
             if (value)
             {
                 sprintf(path, "%s/%s", image_path, (const char *) value);
index c302a02fdb6cd977acc6d902aedc14d964659a2d..0b0ba8a557d2a45dc9b588d4149052dd5d65e545 100644 (file)
@@ -890,11 +890,11 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
        }
 
        if (pvt->use_ecm) {
-               t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6 | T30_SUPPORT_COMPRESSION_T85 | T30_SUPPORT_COMPRESSION_T85_L0);
+               t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6 | T4_SUPPORT_COMPRESSION_T85 | T4_SUPPORT_COMPRESSION_T85_L0);
                t30_set_ecm_capability(t30, TRUE);
                switch_channel_set_variable(channel, "fax_ecm_requested", "1");
        } else {
-               t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D);
+               t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D);
                switch_channel_set_variable(channel, "fax_ecm_requested", "0");
        }