A cleanup of FAX image size/resolution matching accuracy. Squashing of bi-level

images should now be correct. This is now close to supporting grey scale and
colour.
This commit is contained in:
Steve Underwood 2013-08-06 02:38:06 +08:00
parent 13e8532398
commit df669f700a
12 changed files with 1860 additions and 766 deletions

View File

@ -1,121 +1,80 @@
Building and installing spandsp
===============================
A number of distributions include spandsp, but they usually use older versions
of the library, which lack a lot of the features of the current version. Before
installing spandsp, make sure there are no older versions already on your
machine. Make sure libtiff is installed on your machine. Versions 3.5.7,
3.6.0, 3.7.1 and 3.8.2 seem to work OK. There have been several bugs related
to FAX document handling in some versions of libtiff. Also, some people have
had trouble using spandsp because they had more than one version of libtiff
on their machine. Take care with this. If you are using an RPM based system,
such as RedHat or Fedora, you will need the libtiff and libtiff-devel RPMs
installed to be able to build spandsp.
You can use the usual:
./configure
make
make install
process to build the spandsp library. Note that if you use configure in this
way, the software will be installed in /usr/local. In this case make sure your
/etc/ld.so.conf file has an entry for /usr/local/lib. If you wish the software
to be installed in /usr, you should build it with the commands.
./configure --prefix=/usr
make
make install
Building the programming documentation
======================================
If you wish to build the programming documentation for spandsp, configure
spandsp with:
./configure --enable-doc
You need doxygen installed on your machine.
Building the test suite
=======================
Most sections of the spandsp library have an accompanying test program in the
test directory. If you wish to build these test programs, configure spandsp
with:
./configure --enable-tests
To build these tests you will need libaudiofile installed on your machine. To
build the modem tests, with the GUI monitoring feature you will need Fltk 1.1.4
or later, an audio meter module and a cartesian plotting module. Fltk may be
obtained from http://www.fltk.org. The audio meter module may be obtained from
http://www.soft-switch.org/downloads/Fl_Audio_Meter.tgz . The cartesian plotting
module may be obtained from http://134.226.68.29/fltk. However, there is no
suitable makefile supplied with that. You can find a version at
http://www.soft-switch.org/downloads/Fl_Cartesian.tgz which will build as a
Linux library. The actual code in both these versions is identical.
You need to have Fltk 1.1.4 or later installed before building the plotting
library.
Applications
============
Applications support for spandsp is built into packages such as Callweaver,
FreeSwitch and iaxmodem. Code to add spandsp based FAX support to Asterisk may
be found at http://sourceforge.net/projects/agx-ast-addons.
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
These are generic installation instructions.
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' is used to create `configure' by a program
called `autoconf'. You only need `configure.ac' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
`./configure' to configure the package for your system.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation.
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. You can remove the program binaries and object files from the
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
@ -124,62 +83,119 @@ The simplest way to compile this package is:
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
@ -192,25 +208,80 @@ find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
where SYSTEM can have one of these forms:
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
@ -223,19 +294,56 @@ default values for variables like `CC', `cache_file', and `prefix'.
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
@ -248,8 +356,15 @@ operates.
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`configure' also accepts some other, not widely useful, options.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@ -34,7 +34,7 @@ EXTRA_DIST = libspandsp_sim.dsp \
msvc/vc9proj.head \
msvc/vc9proj.foot
INCLUDES = -I$(top_builddir) -I$(top_builddir)/src -DDATADIR="\"$(pkgdatadir)\""
AM_CPPFLAGS = -I$(top_builddir) -I$(top_builddir)/src -DDATADIR="\"$(pkgdatadir)\""
noinst_PROGRAMS = make_line_models

View File

@ -78,7 +78,7 @@ EXTRA_DIST = floating_fudge.h \
spandsp/private/README \
spandsp/version.h.in
INCLUDES = -I$(top_builddir)
AM_CPPFLAGS = -I$(top_builddir)
lib_LTLIBRARIES = libspandsp.la

View File

@ -323,12 +323,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
int supported_bilevel_resolutions,
int supported_colour_resolutions);
/*! \brief Set the compression for the encoded data.
\param s The T.4 context.
\param encoding The encoding.
\return 0 for success, otherwise -1. */
SPAN_DECLARE(int) t4_tx_set_tx_encoding(t4_tx_state_t *s, int encoding);
/*! \brief Set the minimum number of encoded bits per row. This allows the
makes the encoding process to be set to comply with the minimum row
time specified by a remote receiving machine.
@ -336,11 +330,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_encoding(t4_tx_state_t *s, int encoding);
\param bits The minimum number of bits per row. */
SPAN_DECLARE(void) t4_tx_set_min_bits_per_row(t4_tx_state_t *s, int bits);
/*! \brief Set the width of the image.
\param s The T.4 context.
\param image_width The image width, in pixels. */
SPAN_DECLARE(void) t4_tx_set_image_width(t4_tx_state_t *s, int image_width);
/*! \brief Set the maximum number of 2D encoded rows between 1D encoded rows. This
is only valid for T.4 2D encoding.
\param s The T.4 context.
@ -381,12 +370,6 @@ SPAN_DECLARE(void) t4_tx_set_header_overlays_image(t4_tx_state_t *s, int header_
\return 0 for success, otherwise -1. */
SPAN_DECLARE(int) t4_tx_set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler, void *user_data);
/*! \brief Set the row squashing ratio, for adjusting row-to-row (y) resolution of bi-level
images for a T.4 transmit context.
\param s The T.4 transmit context.
\param row_squashing_ratio Vertical squashing ratio. */
SPAN_DECLARE(void) t4_tx_set_row_squashing_ratio(t4_tx_state_t *s, int row_squashing_ratio);
/*! \brief Get the number of pages in the file.
\param s The T.4 context.
\return The number of pages, or -1 if there is an error. */

View File

@ -1224,7 +1224,7 @@ int t30_build_dis_or_dtc(t30_state_t *s)
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_3);
//}
//if ((s->supported_compressions & (T4_COMPRESSION_COLOUR | T4_COMPRESSION_GRAYSCALE)))
if ((s->supported_compressions & (T4_COMPRESSION_COLOUR | T4_COMPRESSION_GRAYSCALE)))
{
if ((s->supported_compressions & T4_COMPRESSION_COLOUR))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE);
@ -1249,8 +1249,8 @@ int t30_build_dis_or_dtc(t30_state_t *s)
if ((s->supported_compressions & T4_COMPRESSION_12BIT))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE);
//if ((s->supported_compressions & T4_COMPRESSION_NO_SUBSAMPLING))
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
if ((s->supported_compressions & T4_COMPRESSION_NO_SUBSAMPLING))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
/* No custom illuminant */
/* No custom gamut range */
@ -1423,8 +1423,6 @@ static int prune_dis_dtc(t30_state_t *s)
static int build_dcs(t30_state_t *s)
{
int i;
int bad;
int row_squashing_ratio;
int use_bilevel;
int image_type;
@ -1523,229 +1521,21 @@ static int build_dcs(t30_state_t *s)
break;
}
/* Set the Y resolution bits */
row_squashing_ratio = 1;
bad = T30_ERR_NORESSUPPORT;
if ((use_bilevel && (s->current_page_resolution & s->mutual_bilevel_resolutions))
||
(!use_bilevel && (s->current_page_resolution & s->mutual_colour_resolutions)))
{
/* The resolution is supported by both parties */
switch (s->current_page_resolution)
{
case T4_RESOLUTION_1200_1200:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200);
break;
case T4_RESOLUTION_600_1200:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_600_600:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600);
break;
case T4_RESOLUTION_400_800:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_400_400:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
break;
case T4_RESOLUTION_300_600:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_300_300:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
break;
case T4_RESOLUTION_200_400:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_200_200:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
break;
case T4_RESOLUTION_200_100:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_100_100:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100);
break;
case T4_RESOLUTION_R16_SUPERFINE:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
break;
case T4_RESOLUTION_R8_SUPERFINE:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
break;
case T4_RESOLUTION_R8_FINE:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
break;
case T4_RESOLUTION_R8_STANDARD:
/* Nothing special to set */
break;
}
bad = T30_ERR_OK;
}
else
{
#if 0
/* Deal with resolution fudging */
if ((s->current_page_resolution & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
{
if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100)))
{
/* Fudge between imperial and metric */
}
}
else if ((s->current_page_resolution & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100))
{
if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
{
/* Fudge between imperial and metric */
}
}
#endif
/* Deal with squashing options */
if ((s->current_page_resolution & T4_RESOLUTION_R8_SUPERFINE))
{
if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_FINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
row_squashing_ratio = 2;
bad = T30_ERR_OK;
}
else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
{
row_squashing_ratio = 4;
bad = T30_ERR_OK;
}
}
else if ((s->current_page_resolution & T4_RESOLUTION_R8_FINE) && (s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
{
row_squashing_ratio = 2;
bad = T30_ERR_OK;
}
else if ((s->current_page_resolution & T4_RESOLUTION_200_400))
{
if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
row_squashing_ratio = 2;
bad = T30_ERR_OK;
}
else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
{
row_squashing_ratio = 4;
bad = T30_ERR_OK;
}
}
else if ((s->current_page_resolution & T4_RESOLUTION_200_200) && (s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
{
row_squashing_ratio = 2;
bad = T30_ERR_OK;
}
}
t4_tx_set_row_squashing_ratio(&s->t4.tx, row_squashing_ratio);
if (bad != T30_ERR_OK)
{
t30_set_status(s, bad);
span_log(&s->logging, SPAN_LOG_FLOW, "Image resolution (%d x %d) not acceptable\n", s->x_resolution, s->y_resolution);
return -1;
}
/* Deal with the image width. */
/* Low (R4) res widths are not supported in recent versions of T.30 */
bad = T30_ERR_OK;
/* The following treats a width field of 11 like 10, which does what note 6 of Table 2/T.30
says we should do with the invalid value 11. */
if (((s->image_width == T4_WIDTH_200_A4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
||
((s->image_width == T4_WIDTH_300_A4) && (s->x_resolution == T4_X_RESOLUTION_300))
||
((s->image_width == T4_WIDTH_400_A4) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16))
||
((s->image_width == T4_WIDTH_600_A4) && (s->x_resolution == T4_X_RESOLUTION_600))
||
((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
/* Set the image width */
switch (s->line_width_code)
{
case T4_SUPPORT_WIDTH_215MM:
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
/* No width related bits need to be set. */
}
else if (((s->image_width == T4_WIDTH_200_B4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
||
((s->image_width == T4_WIDTH_300_B4) && (s->x_resolution == T4_X_RESOLUTION_300))
||
((s->image_width == T4_WIDTH_400_B4) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16))
||
((s->image_width == T4_WIDTH_600_B4) && (s->x_resolution == T4_X_RESOLUTION_600))
||
((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_255MM))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
}
else
{
/* We do not support this width and resolution combination */
bad = T30_ERR_NOSIZESUPPORT;
}
}
else if (((s->image_width == T4_WIDTH_200_A3) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
||
((s->image_width == T4_WIDTH_300_A3) && (s->x_resolution == T4_X_RESOLUTION_300))
||
((s->image_width == T4_WIDTH_400_A3) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16))
||
((s->image_width == T4_WIDTH_600_A3) && (s->x_resolution == T4_X_RESOLUTION_600))
||
((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_303MM))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
}
else
{
/* We do not support this width and resolution combination */
bad = T30_ERR_NOSIZESUPPORT;
}
}
else
{
/* We do not support this width and resolution combination */
bad = T30_ERR_NOSIZESUPPORT;
}
if (bad != T30_ERR_OK)
{
t30_set_status(s, bad);
span_log(&s->logging,
SPAN_LOG_FLOW,
"Image width (%d pixels) and resolution (%d x %d) is not an acceptable\n",
s->image_width,
s->x_resolution,
s->y_resolution);
return -1;
break;
case T4_SUPPORT_WIDTH_255MM:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
break;
case T4_SUPPORT_WIDTH_303MM:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
break;
}
/* Set the image length */
@ -1760,6 +1550,77 @@ static int build_dcs(t30_state_t *s)
else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_US_LEGAL))
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NORTH_AMERICAN_LEGAL);
/* Set the Y resolution bits */
switch (s->current_page_resolution)
{
case T4_RESOLUTION_1200_1200:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200);
break;
case T4_RESOLUTION_600_1200:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_600_600:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600);
break;
case T4_RESOLUTION_400_800:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_400_400:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
break;
case T4_RESOLUTION_300_600:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_300_300:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
break;
case T4_RESOLUTION_200_400:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_200_200:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
break;
case T4_RESOLUTION_200_100:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
break;
case T4_RESOLUTION_100_100:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
if (!use_bilevel)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100);
break;
case T4_RESOLUTION_R16_SUPERFINE:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
break;
case T4_RESOLUTION_R8_SUPERFINE:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
break;
case T4_RESOLUTION_R8_FINE:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
break;
case T4_RESOLUTION_R8_STANDARD:
/* Nothing special to set */
break;
}
if (s->error_correcting_mode)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_ECM_MODE);
@ -1832,7 +1693,7 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
if (!s->error_correcting_mode)
{
/* Remove any compression schemes which need error correction to work. */
s->mutual_compressions &= (0xF0000000 | T4_COMPRESSION_NONE | T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D);
s->mutual_compressions &= (0xFF800000 | T4_COMPRESSION_NONE | T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D);
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
s->mutual_compressions &= ~T4_COMPRESSION_T4_2D;
}
@ -1866,8 +1727,8 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
s->mutual_compressions &= ~T4_COMPRESSION_12BIT;
//if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
// ???? = T4_COMPRESSION_T42_T81_SUBSAMPLING;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
s->mutual_compressions &= ~T4_COMPRESSION_NO_SUBSAMPLING;
/* bit74 custom illuminant */
/* bit75 custom gamut range */
@ -2087,7 +1948,7 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING))
{
//???? = T4_COMPRESSION_T42_T81_SUBSAMPLING;
//???? = T4_COMPRESSION_NO_SUBSAMPLING;
}
if (!test_ctrl_bit(dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES))
@ -2529,7 +2390,6 @@ static int send_dcs_sequence(t30_state_t *s, int start)
/* Schedule training after the messages */
if (start)
{
prune_dcs(s);
set_state(s, T30_STATE_D);
s->step = 0;
}
@ -2654,22 +2514,12 @@ static void set_min_scan_time(t30_state_t *s)
{
case T4_Y_RESOLUTION_SUPERFINE:
case T4_Y_RESOLUTION_400:
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
{
s->min_scan_time_code = translate_min_scan_time[(test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MIN_SCAN_TIME_HALVES)) ? 2 : 1][min_bits_field];
break;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support super-fine resolution. Squashing image.\n");
/* Fall through */
s->min_scan_time_code = translate_min_scan_time[(test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MIN_SCAN_TIME_HALVES)) ? 2 : 1][min_bits_field];
break;
case T4_Y_RESOLUTION_FINE:
case T4_Y_RESOLUTION_200:
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
{
s->min_scan_time_code = translate_min_scan_time[1][min_bits_field];
break;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support fine resolution. Squashing image.\n");
/* Fall through */
s->min_scan_time_code = translate_min_scan_time[1][min_bits_field];
break;
case T4_Y_RESOLUTION_STANDARD:
case T4_Y_RESOLUTION_100:
s->min_scan_time_code = translate_min_scan_time[0][min_bits_field];
@ -2689,6 +2539,8 @@ static void set_min_scan_time(t30_state_t *s)
static int start_sending_document(t30_state_t *s)
{
int res;
if (s->tx_file[0] == '\0')
{
/* There is nothing to send */
@ -2703,27 +2555,68 @@ static int start_sending_document(t30_state_t *s)
return -1;
}
s->operation_in_progress = OPERATION_IN_PROGRESS_T4_TX;
t4_tx_get_pages_in_file(&s->t4.tx);
t4_tx_set_tx_encoding(&s->t4.tx, s->line_compression);
t4_tx_set_local_ident(&s->t4.tx, s->tx_info.ident);
t4_tx_set_header_info(&s->t4.tx, s->header_info);
if (s->use_own_tz)
t4_tx_set_header_tz(&s->t4.tx, &s->tz);
if (tx_start_page(s))
t4_tx_get_pages_in_file(&s->t4.tx);
if ((res = t4_tx_set_tx_image_format(&s->t4.tx,
s->mutual_compressions,
s->mutual_image_sizes,
s->mutual_bilevel_resolutions,
s->mutual_colour_resolutions)) < 0)
{
span_log(&s->logging, SPAN_LOG_WARNING, "Something seems to be wrong in the file\n");
t30_set_status(s, T30_ERR_FILEERROR);
switch (res)
{
case T4_IMAGE_FORMAT_INCOMPATIBLE:
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image format\n");
t30_set_status(s, T30_ERR_BADTIFFHDR);
break;
case T4_IMAGE_FORMAT_NOSIZESUPPORT:
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image size\n");
t30_set_status(s, T30_ERR_NOSIZESUPPORT);
break;
case T4_IMAGE_FORMAT_NORESSUPPORT:
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image resolution\n");
t30_set_status(s, T30_ERR_NORESSUPPORT);
break;
default:
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot negotiate an image format\n");
t30_set_status(s, T30_ERR_BADTIFF);
break;
}
return -1;
}
s->line_image_type = t4_tx_get_tx_image_type(&s->t4.tx);
s->line_compression = t4_tx_get_tx_compression(&s->t4.tx);
s->image_width = t4_tx_get_tx_image_width(&s->t4.tx);
s->line_width_code = t4_tx_get_tx_image_width_code(&s->t4.tx);
s->x_resolution = t4_tx_get_tx_x_resolution(&s->t4.tx);
s->y_resolution = t4_tx_get_tx_y_resolution(&s->t4.tx);
s->image_width = t4_tx_get_tx_image_width(&s->t4.tx);
/* The minimum scan time to be used can't be evaluated until we know the Y resolution, and
must be evaluated before the minimum scan row bits can be evaluated. */
s->current_page_resolution = t4_tx_get_tx_resolution(&s->t4.tx);
span_log(&s->logging,
SPAN_LOG_FLOW,
"Choose image type %s (%d), compression %s (%d)\n",
t4_image_type_to_str(s->line_image_type),
s->line_image_type,
t4_compression_to_str(s->line_compression),
s->line_compression);
/* The minimum scan time to be used can't be evaluated until we know the Y resolution. */
set_min_scan_time(s);
if (tx_start_page(s))
{
span_log(&s->logging, SPAN_LOG_WARNING, "Something seems to be wrong in the file\n");
t30_set_status(s, T30_ERR_BADTIFFHDR);
return -1;
}
if (s->error_correcting_mode)
{
if (get_partial_ecm_page(s) == 0)
@ -2795,21 +2688,6 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
send_dcn(s);
return -1;
}
/* Choose a compression scheme from amongst those mutually available */
if ((s->mutual_compressions & T4_COMPRESSION_T85_L0))
s->line_compression = T4_COMPRESSION_T85_L0;
else if ((s->mutual_compressions & T4_COMPRESSION_T85))
s->line_compression = T4_COMPRESSION_T85;
else if ((s->mutual_compressions & T4_COMPRESSION_T6))
s->line_compression = T4_COMPRESSION_T6;
else if ((s->mutual_compressions & T4_COMPRESSION_T4_2D))
s->line_compression = T4_COMPRESSION_T4_2D;
else
s->line_compression = T4_COMPRESSION_T4_1D;
span_log(&s->logging, SPAN_LOG_FLOW, "Choose compression %s (%d)\n", t4_compression_to_str(s->line_compression), s->line_compression);
if (s->phase_b_handler)
{
new_status = s->phase_b_handler(s, s->phase_b_user_data, msg[2]);
@ -6825,7 +6703,7 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
| T4_SUPPORT_LENGTH_UNLIMITED;
/* Set the output encoding to something safe. Most things get 1D and 2D
encoding right. Quite a lot get other things wrong. */
s->supported_output_compressions = T4_COMPRESSION_T4_2D;
s->supported_output_compressions = T4_COMPRESSION_T4_2D | T4_COMPRESSION_T42_T81;
s->local_min_scan_time_code = T30_MIN_SCAN_0MS;
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
span_log_set_protocol(&s->logging, "T.30");

View File

@ -234,11 +234,24 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
#endif
#if defined(SPANDSP_SUPPORT_T42)
case T4_COMPRESSION_T42_T81:
output_compression = COMPRESSION_JPEG;
bits_per_sample = 8;
if (t->image_type == T4_IMAGE_TYPE_COLOUR_8BIT)
{
samples_per_pixel = 3;
photometric = PHOTOMETRIC_YCBCR; //PHOTOMETRIC_ITULAB;
}
else
{
samples_per_pixel = 1;
photometric = PHOTOMETRIC_MINISBLACK;
}
break;
case T4_COMPRESSION_SYCC_T81:
output_compression = COMPRESSION_JPEG;
bits_per_sample = 8;
samples_per_pixel = 3;
photometric = PHOTOMETRIC_ITULAB;
photometric = PHOTOMETRIC_YCBCR;
break;
#endif
#if defined(SPANDSP_SUPPORT_T43)
@ -288,6 +301,13 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
TIFFSetField(t->tiff_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, photometric);
TIFFSetField(t->tiff_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
if (t->compression == T4_COMPRESSION_T42_T81)
{
TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 2, 2);
//TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 1, 1);
TIFFSetField(t->tiff_file, TIFFTAG_JPEGQUALITY, 75);
TIFFSetField(t->tiff_file, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
}
/* TIFFTAG_STRIPBYTECOUNTS and TIFFTAG_STRIPOFFSETS are added automatically */
x_resolution = s->metadata.x_resolution/100.0f;
@ -344,30 +364,32 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
is always one greater than the highest page number in the file. */
s->tiff.pages_in_file = s->current_page + 1;
s->metadata.image_length = 0;
switch (s->metadata.compression)
switch (s->current_decoder)
{
case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D:
/* We only get bad row info from pages received in non-ECM mode. */
if (output_compression == COMPRESSION_CCITT_T4)
case 0:
s->metadata.image_length = 1024;
break;
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
if ((s->metadata.compression & (T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D)))
{
if (s->decoder.t4_t6.bad_rows)
/* We only get bad row info from pages received in non-ECM mode. */
if (output_compression == COMPRESSION_CCITT_T4)
{
TIFFSetField(t->tiff_file, TIFFTAG_BADFAXLINES, s->decoder.t4_t6.bad_rows);
TIFFSetField(t->tiff_file, TIFFTAG_CONSECUTIVEBADFAXLINES, s->decoder.t4_t6.longest_bad_row_run);
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_REGENERATED);
}
else
{
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN);
if (s->decoder.t4_t6.bad_rows)
{
TIFFSetField(t->tiff_file, TIFFTAG_BADFAXLINES, s->decoder.t4_t6.bad_rows);
TIFFSetField(t->tiff_file, TIFFTAG_CONSECUTIVEBADFAXLINES, s->decoder.t4_t6.longest_bad_row_run);
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_REGENERATED);
}
else
{
TIFFSetField(t->tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN);
}
}
}
/* Fall through */
case T4_COMPRESSION_T6:
s->metadata.image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
s->metadata.image_length = t85_decode_get_image_length(&s->decoder.t85);
break;
#if defined(SPANDSP_SUPPORT_T88)
@ -401,6 +423,34 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
/* Create a placeholder for the global parameters IFD, to be filled in later */
TIFFSetField(t->tiff_file, TIFFTAG_GLOBALPARAMETERSIFD, 0);
}
#if 0
/* Paletised image? */
TIFFSetField(t->tiff_file, TIFFTAG_INDEXED, 1);
/* T.44 mode */
TIFFSetField(t->tiff_file, TIFFTAG_MODENUMBER, 0);
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 2\n");
{
float xxx[] = {20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0};
TIFFSetField(t->tiff_file, TIFFTAG_DECODE, (uint16) 2*samples_per_pixel, xxx);
}
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 3\n");
{
uint16_t xxx[] = {12, 34, 45, 67};
TIFFSetField(t->tiff_file, TIFFTAG_IMAGEBASECOLOR, (uint16_t) samples_per_pixel, xxx);
}
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 4\n");
TIFFSetField(t->tiff_file, TIFFTAG_T82OPTIONS, 0);
{
uint32_t xxx[] = {34, 56, 78, 90};
TIFFSetField(t->tiff_file, TIFFTAG_STRIPROWCOUNTS, (uint16_t) 5, xxx);
}
span_log(&s->logging, SPAN_LOG_FLOW, "TIFF/FX stuff 5\n");
{
uint32_t xxx[] = {2, 3};
TIFFSetField(t->tiff_file, TIFFTAG_IMAGELAYER, xxx);
}
#endif
#endif
return 0;
}
@ -450,10 +500,10 @@ static int write_tiff_t85_image(t4_rx_state_t *s)
if (buf_len < image_len + 65536)
{
buf_len += 65536;
if ((buf2 = realloc(buf, buf_len)) == NULL)
if ((buf2 = span_realloc(buf, buf_len)) == NULL)
{
if (buf)
free(buf);
span_free(buf);
return -1;
}
buf = buf2;
@ -468,7 +518,7 @@ static int write_tiff_t85_image(t4_rx_state_t *s)
return -1;
}
t85_encode_release(&t85);
free(buf);
span_free(buf);
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -496,10 +546,10 @@ static int write_tiff_t43_image(t4_rx_state_t *s)
if (buf_len < image_len + 65536)
{
buf_len += 65536;
if ((buf2 = realloc(buf, buf_len)) == NULL)
if ((buf2 = span_realloc(buf, buf_len)) == NULL)
{
if (buf)
free(buf);
span_free(buf);
return -1;
}
buf = buf2;
@ -511,7 +561,7 @@ static int write_tiff_t43_image(t4_rx_state_t *s)
if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, buf, image_len) < 0)
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file);
t43_encode_release(&t43);
free(buf);
span_free(buf);
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -525,49 +575,57 @@ static int write_tiff_image(t4_rx_state_t *s)
#endif
t = &s->tiff;
if (t->image_buffer == NULL || t->image_size <= 0)
if (s->pre_encoded_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0))
return -1;
/* Set up the TIFF directory info... */
set_tiff_directory_info(s);
/* ...Put the directory in the file before the image data, to get them in the order specified
for TIFF/F files... */
if (!TIFFCheckpointDirectory(t->tiff_file))
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page);
//if (!TIFFCheckpointDirectory(t->tiff_file))
// span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page);
/* ...and write out the image... */
switch (t->compression)
if (s->pre_encoded_ptr > 0)
{
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t85_image(s) < 0)
return -1;
break;
if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->pre_encoded_buf, s->pre_encoded_ptr) < 0)
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file);
}
else
{
switch (t->compression)
{
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t85_image(s) < 0)
return -1;
break;
#if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t88_image(s) < 0)
return -1;
break;
case T4_COMPRESSION_T88:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t88_image(s) < 0)
return -1;
break;
#endif
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t43_image(s) < 0)
return -1;
break;
case T4_COMPRESSION_T43:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t43_image(s) < 0)
return -1;
break;
#endif
#if defined(SPANDSP_SUPPORT_T45)
case T4_COMPRESSION_T45:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t45_image(s) < 0)
return -1;
break;
case T4_COMPRESSION_T45:
/* We need to perform this compression here, as libtiff does not understand it. */
if (write_tiff_t45_image(s) < 0)
return -1;
break;
#endif
default:
/* Let libtiff do the compression */
if (TIFFWriteEncodedStrip(t->tiff_file, 0, t->image_buffer, t->image_size) < 0)
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", t->file);
break;
default:
/* Let libtiff do the compression */
if (TIFFWriteEncodedStrip(t->tiff_file, 0, t->image_buffer, t->image_size) < 0)
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", t->file);
break;
}
}
/* ...then finalise the directory entry, and libtiff is happy. */
if (!TIFFWriteDirectory(t->tiff_file))
@ -633,7 +691,7 @@ static int close_tiff_output_file(t4_rx_state_t *s)
put in it. */
if (s->current_page == 0)
remove(s->tiff.file);
free((char *) s->tiff.file);
span_free((char *) s->tiff.file);
}
s->tiff.file = NULL;
return 0;
@ -646,7 +704,7 @@ static void tiff_rx_release(t4_rx_state_t *s)
close_tiff_output_file(s);
if (s->tiff.image_buffer)
{
free(s->tiff.image_buffer);
span_free(s->tiff.image_buffer);
s->tiff.image_buffer = NULL;
s->tiff.image_size = 0;
s->tiff.image_buffer_size = 0;
@ -673,10 +731,10 @@ SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len)
if (s->pre_encoded_len < s->pre_encoded_ptr + 65536)
{
s->pre_encoded_len += 65536;
if ((buf2 = realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL)
if ((buf2 = span_realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL)
{
if (s->pre_encoded_buf)
free(s->pre_encoded_buf);
span_free(s->pre_encoded_buf);
return -1;
}
s->pre_encoded_buf = buf2;
@ -757,11 +815,19 @@ static void select_tiff_compression(t4_rx_state_t *s, int output_image_type)
else if ((s->supported_tiff_compressions & T4_COMPRESSION_T43))
s->tiff.compression = T4_COMPRESSION_T43;
}
s->tiff.image_type = output_image_type;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
{
#if 0
output_image_type = T4_IMAGE_TYPE_BILEVEL;
s->metadata.compression = compression;
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
s->current_decoder = 0;
return 0;
#else
switch (compression)
{
case T4_COMPRESSION_T4_1D:
@ -775,6 +841,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
break;
default:
t4_t6_decode_init(&s->decoder.t4_t6, compression, s->metadata.image_width, s->row_handler, s->row_handler_user_data);
s->current_decoder = T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6;
break;
}
s->metadata.compression = compression;
@ -789,14 +856,15 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
break;
default:
t85_decode_init(&s->decoder.t85, s->row_handler, s->row_handler_user_data);
s->current_decoder = T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0;
/* Constrain received images to the maximum width of any FAX. This will
avoid one potential cause of trouble, where a bad received image has
a gigantic dimension that sucks our memory dry. */
t85_decode_set_image_size_constraints(&s->decoder.t85, T4_WIDTH_1200_A3, 0);
break;
}
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
s->metadata.compression = compression;
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
return 0;
#if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88:
@ -805,10 +873,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
case T4_COMPRESSION_T88:
break;
default:
t88_decode_init(&s->decoder.t88, s->row_handler, s->row_handler_user_data);
s->current_decoder = T4_COMPRESSION_T88;
break;
}
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
s->metadata.compression = compression;
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
return 0;
#endif
case T4_COMPRESSION_T42_T81:
@ -820,6 +890,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
break;
default:
t42_decode_init(&s->decoder.t42, s->row_handler, s->row_handler_user_data);
s->current_decoder = T4_COMPRESSION_T42_T81;
/* Constrain received images to the maximum width of any FAX. This will
avoid one potential cause of trouble, where a bad received image has
a gigantic dimension that sucks our memory dry. */
@ -837,6 +908,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
break;
default:
t43_decode_init(&s->decoder.t43, s->row_handler, s->row_handler_user_data);
s->current_decoder = T4_COMPRESSION_T43;
/* Constrain received images to the maximum width of any FAX. This will
avoid one potential cause of trouble, where a bad received image has
a gigantic dimension that sucks our memory dry. */
@ -854,6 +926,8 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
case T4_COMPRESSION_T45:
break;
default:
t45_decode_init(&s->decoder.t45, s->row_handler, s->row_handler_user_data);
s->current_decoder = T4_COMPRESSION_T45;
break;
}
s->metadata.compression = compression;
@ -863,6 +937,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
}
return -1;
#endif
}
/*- End of function --------------------------------------------------------*/
@ -876,14 +951,11 @@ SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_rx_state_t *s, t4_row_write_han
{
s->row_handler = handler;
s->row_handler_user_data = user_data;
switch (s->metadata.compression)
switch (s->current_decoder)
{
case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
return t4_t6_decode_set_row_write_handler(&s->decoder.t4_t6, handler, user_data);
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
return t85_decode_set_row_write_handler(&s->decoder.t85, handler, user_data);
#if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88:
@ -914,12 +986,11 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
t->image_y_resolution = s->metadata.y_resolution;
t->x_resolution = s->metadata.x_resolution;
t->y_resolution = s->metadata.y_resolution;
t->compression = s->metadata.compression;
switch (s->metadata.compression)
switch (s->current_decoder)
{
case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
t->type = T4_IMAGE_TYPE_BILEVEL;
t->width = t4_t6_decode_get_image_width(&s->decoder.t4_t6);
t->length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
@ -930,8 +1001,7 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
t->bad_rows = s->decoder.t4_t6.bad_rows;
t->longest_bad_row_run = s->decoder.t4_t6.longest_bad_row_run;
break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
t->type = T4_IMAGE_TYPE_BILEVEL;
t->width = t85_decode_get_image_width(&s->decoder.t85);
t->length = t85_decode_get_image_length(&s->decoder.t85);
@ -945,7 +1015,7 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
break;
#endif
case T4_COMPRESSION_T42_T81:
t->type = T4_IMAGE_TYPE_COLOUR_8BIT; //T4_IMAGE_TYPE_GRAY_8BIT;
t->type = T4_IMAGE_TYPE_GRAY_8BIT; //T4_IMAGE_TYPE_COLOUR_8BIT;
t->width = t42_decode_get_image_width(&s->decoder.t42);
t->length = t42_decode_get_image_length(&s->decoder.t42);
t->image_type = t->type;
@ -976,21 +1046,18 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Start rx page %d - compression %s\n", s->current_page, t4_compression_to_str(s->metadata.compression));
switch (s->metadata.compression)
switch (s->current_decoder)
{
case 0:
s->pre_encoded_ptr = 0;
s->pre_encoded_len = 0;
s->image_put_handler = NULL;
break;
case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
t4_t6_decode_restart(&s->decoder.t4_t6, s->metadata.image_width);
s->image_put_handler = (t4_image_put_handler_t) t4_t6_decode_put;
break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
t85_decode_restart(&s->decoder.t85);
s->image_put_handler = (t4_image_put_handler_t) t85_decode_put;
break;
@ -1036,7 +1103,7 @@ static int tiff_row_write_handler(void *user_data, const uint8_t buf[], size_t l
{
if (s->tiff.image_size + len >= s->tiff.image_buffer_size)
{
if ((t = realloc(s->tiff.image_buffer, s->tiff.image_buffer_size + 100*len)) == NULL)
if ((t = span_realloc(s->tiff.image_buffer, s->tiff.image_buffer_size + 100*len)) == NULL)
return -1;
s->tiff.image_buffer_size += 100*len;
s->tiff.image_buffer = t;
@ -1057,15 +1124,15 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
if (s->image_put_handler)
s->image_put_handler((void *) &s->decoder, NULL, 0);
switch (s->metadata.compression)
switch (s->current_decoder)
{
case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
case 0:
length = s->pre_encoded_ptr;
break;
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
length = t85_decode_get_image_length(&s->decoder.t85);
break;
#if defined(SPANDSP_SUPPORT_T88)
@ -1100,6 +1167,7 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
if (write_tiff_image(s) == 0)
s->current_page++;
s->tiff.image_size = 0;
s->pre_encoded_ptr = 0;
}
else
{
@ -1142,6 +1210,7 @@ SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int
s->metadata.y_resolution = T4_Y_RESOLUTION_FINE;
s->current_page = 0;
s->current_decoder = 0;
/* Default handler */
s->row_handler = tiff_row_write_handler;
@ -1153,7 +1222,7 @@ SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int
if (open_tiff_output_file(s, file) < 0)
{
if (allocated)
free(s);
span_free(s);
return NULL;
}
/* Save the file name for logging reports. */
@ -1167,14 +1236,11 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s)
{
if (s->tiff.file)
tiff_rx_release(s);
switch (s->metadata.compression)
switch (s->current_decoder)
{
case T4_COMPRESSION_T4_1D:
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
return t4_t6_decode_release(&s->decoder.t4_t6);
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
return t85_decode_release(&s->decoder.t85);
#if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88:
@ -1200,7 +1266,7 @@ SPAN_DECLARE(int) t4_rx_free(t4_rx_state_t *s)
int ret;
ret = t4_rx_release(s);
free(s);
span_free(s);
return ret;
}
/*- End of function --------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ EXTRA_DIST = fax_tests.sh \
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_builddir)/src -I$(top_builddir)/spandsp-sim -DDATADIR="\"$(pkgdatadir)\""
AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_builddir)/spandsp-sim -DDATADIR="\"$(pkgdatadir)\""
LIBDIR = -L$(top_builddir)/src

View File

@ -43,6 +43,15 @@ then
fi
echo adsi_tests completed OK
./alloc_tests >$STDOUT_DEST 2>$STDERR_DEST
RETVAL=$?
if [ $RETVAL != 0 ]
then
echo alloc_tests failed!
exit $RETVAL
fi
echo alloc_tests completed OK
./async_tests >$STDOUT_DEST 2>$STDERR_DEST
RETVAL=$?
if [ $RETVAL != 0 ]

View 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\x89\x80\x80\x80\x18\x18\xB9\x10\x03"), // For audio FAXing
RESPONSE("\xFF\x13\x80\x00\xEE\xF8\x80\x80\x99\x80\x80\x80\x18\x58\x0D\x10\x03"), // For audio FAXing
#else
RESPONSE("\xFF\x13\x80\x04\xEE\xF8\x80\x80\x89\x80\x80\x80\x18\x84\x09\x10\x03"), // For T.38 FAXing
RESPONSE("\xFF\x13\x80\x04\xEE\xF8\x80\x80\x99\x80\x80\x80\x18\xC4\xBD\x10\x03"), // For T.38 FAXing
#endif
RESPONSE("\r\nOK\r\n"),
//EXCHANGE("AT+FRH=3\r", "\r\nNO CARRIER\r\n"),

View File

@ -518,7 +518,6 @@ int main(int argc, char *argv[])
compression = compression_sequence[compression_step++];
}
}
#if 0
if (t4_tx_set_tx_image_format(send_state,
compression,
T4_SUPPORT_WIDTH_215MM
@ -548,8 +547,6 @@ int main(int argc, char *argv[])
{
break;
}
#endif
t4_tx_set_tx_encoding(send_state, compression);
t4_rx_set_rx_encoding(receive_state, compression);
if (t4_tx_start_page(send_state))

View File

@ -397,6 +397,7 @@ static void fax_prepare(void)
| T4_RESOLUTION_R8_FINE
| T4_RESOLUTION_R8_SUPERFINE
| T4_RESOLUTION_R16_SUPERFINE
| T4_RESOLUTION_100_100
| T4_RESOLUTION_200_100
| T4_RESOLUTION_200_200
| T4_RESOLUTION_200_400
@ -980,7 +981,37 @@ static int next_step(faxtester_state_t *s)
else if (strcasecmp((const char *) compression, "T.6") == 0)
compression_type = T4_COMPRESSION_T6;
}
t4_tx_set_tx_encoding(&t4_tx_state, compression_type);
if (t4_tx_set_tx_image_format(&t4_tx_state,
compression_type,
T4_SUPPORT_WIDTH_215MM
| T4_SUPPORT_LENGTH_US_LETTER
| T4_SUPPORT_LENGTH_US_LEGAL
| T4_SUPPORT_LENGTH_UNLIMITED,
T4_RESOLUTION_R8_STANDARD
| T4_RESOLUTION_R8_FINE
| T4_RESOLUTION_R8_SUPERFINE
| T4_RESOLUTION_R16_SUPERFINE
| T4_RESOLUTION_200_100
| T4_RESOLUTION_200_200
| T4_RESOLUTION_200_400
| T4_RESOLUTION_300_300
| T4_RESOLUTION_300_600
| T4_RESOLUTION_400_400
| T4_RESOLUTION_400_800
| T4_RESOLUTION_600_600
| T4_RESOLUTION_600_1200
| T4_RESOLUTION_1200_1200,
T4_RESOLUTION_100_100
| T4_RESOLUTION_200_200
| T4_RESOLUTION_300_300
| T4_RESOLUTION_400_400
| T4_RESOLUTION_600_600
| T4_RESOLUTION_1200_1200) < 0)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
printf("Test failed\n");
exit(2);
}
t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
if (t4_tx_start_page(&t4_tx_state))
{
@ -1020,7 +1051,37 @@ static int next_step(faxtester_state_t *s)
else if (strcasecmp((const char *) compression, "T.6") == 0)
compression_type = T4_COMPRESSION_T6;
}
t4_tx_set_tx_encoding(&t4_tx_state, compression_type);
if (t4_tx_set_tx_image_format(&t4_tx_state,
compression_type,
T4_SUPPORT_WIDTH_215MM
| T4_SUPPORT_LENGTH_US_LETTER
| T4_SUPPORT_LENGTH_US_LEGAL
| T4_SUPPORT_LENGTH_UNLIMITED,
T4_RESOLUTION_R8_STANDARD
| T4_RESOLUTION_R8_FINE
| T4_RESOLUTION_R8_SUPERFINE
| T4_RESOLUTION_R16_SUPERFINE
| T4_RESOLUTION_200_100
| T4_RESOLUTION_200_200
| T4_RESOLUTION_200_400
| T4_RESOLUTION_300_300
| T4_RESOLUTION_300_600
| T4_RESOLUTION_400_400
| T4_RESOLUTION_400_800
| T4_RESOLUTION_600_600
| T4_RESOLUTION_600_1200
| T4_RESOLUTION_1200_1200,
T4_RESOLUTION_100_100
| T4_RESOLUTION_200_200
| T4_RESOLUTION_300_300
| T4_RESOLUTION_400_400
| T4_RESOLUTION_600_600
| T4_RESOLUTION_1200_1200) < 0)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
printf("Test failed\n");
exit(2);
}
t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
if (t4_tx_start_page(&t4_tx_state))
{