]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Various little tweaks
authorSteve Underwood <steveu@coppice.org>
Sat, 11 Aug 2012 10:32:00 +0000 (18:32 +0800)
committerSteve Underwood <steveu@coppice.org>
Sat, 11 Aug 2012 10:32:00 +0000 (18:32 +0800)
A bug in end of image handling fixed, which could mean some T.85 images would
screw up.

12 files changed:
libs/spandsp/INSTALL
libs/spandsp/src/image_translate.c
libs/spandsp/src/spandsp/t42.h
libs/spandsp/src/spandsp/t4_t6_encode.h
libs/spandsp/src/spandsp/t4_tx.h
libs/spandsp/src/spandsp/t85.h
libs/spandsp/src/t30.c
libs/spandsp/src/t30_api.c
libs/spandsp/src/t42.c
libs/spandsp/src/t4_tx.c
libs/spandsp/src/t85_encode.c
libs/spandsp/tests/image_translate_tests.c

index 2abc70492ac004494ebf754062618079ceb8488d..a1e89e18ad20c227845f2099cb9894c799265d19 100644 (file)
-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-2011 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.
-
-  5. You can remove the program binaries and object files from the
+     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. 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.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
 
-Or on systems that have the `env' program, you can do it like this:
-     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+     ./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.
+
+   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:
 
-   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.
+     ./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
+where SYSTEM can have one of these forms:
+
+     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 host type.
+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 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.
+   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,55 @@ 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 bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
    `configure' recognizes the following options to control how it
 operates.
 
+`--help'
+`-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'
-     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'.
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
 
-`--help'
-     Print a summary of the options to `configure', and exit.
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
 
 `--quiet'
 `--silent'
@@ -248,8 +355,16 @@ 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.
+
+`--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.
 
-`configure' also accepts some other, not widely useful, options.
index 4ee2c211bf3c3bef65efb1f40e041661488fdb61..7ea32099ae4debe82a885ae2cc714889795974e6 100644 (file)
@@ -163,9 +163,9 @@ static int image_gray16_to_colour16_row(uint16_t colour16[], uint16_t gray16[],
 
     for (i = pixels - 1;  i >= 0;  i--)
     {
-        colour16[3*i] = saturateu16((gray16[i]*36532) >> 15);
-        colour16[3*i + 1] = saturateu16((gray16[i]*37216) >> 16);
-        colour16[3*i + 2] = saturateu16((gray16[i]*47900) >> 14);
+        colour16[3*i] = saturateu16((gray16[i]*36532U) >> 15);
+        colour16[3*i + 1] = saturateu16((gray16[i]*37216U) >> 16);
+        colour16[3*i + 2] = saturateu16((gray16[i]*47900U) >> 14);
     }
     return pixels;
 }
@@ -177,9 +177,9 @@ static int image_gray16_to_colour8_row(uint8_t colour8[], uint16_t gray16[], int
 
     for (i = pixels - 1;  i >= 0;  i--)
     {
-        colour8[3*i] = saturateu8((gray16[i]*36532) >> 23);
-        colour8[3*i + 1] = saturateu8((gray16[i]*37216) >> 24);
-        colour8[3*i + 2] = saturateu8((gray16[i]*47900) >> 22);
+        colour8[3*i] = saturateu8((gray16[i]*36532U) >> 23);
+        colour8[3*i + 1] = saturateu8((gray16[i]*37216U) >> 24);
+        colour8[3*i + 2] = saturateu8((gray16[i]*47900U) >> 22);
     }
     return pixels;
 }
@@ -557,6 +557,8 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta
                                                              void *row_read_user_data)
 {
     int i;
+    int raw_row_size;
+    int row_size;
 
     if (s == NULL)
     {
@@ -624,25 +626,29 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta
     }
 
     /* Allocate the two row buffers we need, using the space requirements we now have */
+    raw_row_size = s->input_width*s->input_bytes_per_pixel;
+    row_size = s->output_width*s->output_bytes_per_pixel;
+    if (raw_row_size < row_size)
+        raw_row_size = row_size;
     if (s->resize)
     {
         for (i = 0;  i < 2;  i++)
         {
-            if ((s->raw_pixel_row[i] = (uint8_t *) malloc(s->input_width*s->input_bytes_per_pixel)) == NULL)
+            if ((s->raw_pixel_row[i] = (uint8_t *) malloc(raw_row_size)) == NULL)
                 return NULL;
-            memset(s->raw_pixel_row[i], 0, s->input_width*s->input_bytes_per_pixel);
-            if ((s->pixel_row[i] = (uint8_t *) malloc(s->output_width*sizeof(uint8_t))) == NULL)
+            memset(s->raw_pixel_row[i], 0, raw_row_size);
+            if ((s->pixel_row[i] = (uint8_t *) malloc(row_size)) == NULL)
                 return NULL;
-            memset(s->pixel_row[i], 0, s->output_width*sizeof(uint8_t));
+            memset(s->pixel_row[i], 0, row_size);
         }
     }
     else
     {
         for (i = 0;  i < 2;  i++)
         {
-            if ((s->pixel_row[i] = (uint8_t *) malloc(s->output_width*s->input_bytes_per_pixel)) == NULL)
+            if ((s->pixel_row[i] = (uint8_t *) malloc(raw_row_size)) == NULL)
                 return NULL;
-            memset(s->pixel_row[i], 0, s->output_width*s->input_bytes_per_pixel);
+            memset(s->pixel_row[i], 0, raw_row_size);
         }
     }
 
index e072b074423b1036ad634a8313c6a4b47fdbaaf6..a1441c0406457e1138f6274aa5a00086e7db92fc 100644 (file)
@@ -81,6 +81,11 @@ SPAN_DECLARE(void) t42_encode_abort(t42_encode_state_t *s);
 
 SPAN_DECLARE(void) t42_encode_comment(t42_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.42 context.
+    \return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */
+SPAN_DECLARE(int) t42_encode_check_if_complete(t42_encode_state_t *s);
+
 SPAN_DECLARE(int) t42_encode_get_byte(t42_encode_state_t *s);
 
 SPAN_DECLARE(int) t42_encode_get_chunk(t42_encode_state_t *s, uint8_t buf[], int max_len);
index 975b68ce218c3e10f020b60e9cd042e71f3141b2..6e30cb71f684f32818d9d2a2ac12dd14a73e9889 100644 (file)
@@ -38,15 +38,13 @@ extern "C" {
            moving forward in the buffer. The document will be padded for the
            current minimum scan line time.
     \param s The T.4/T.6 context.
-    \return The next bit (i.e. 0 or 1). For the last bit of data, bit 1 is
-            set (i.e. the returned value is 2 or 3). */
+    \return The next bit (i.e. 0 or 1). SIG_STATUS_END_OF_DATA for no more data. */
 SPAN_DECLARE(int) t4_t6_encode_check_bit(t4_t6_encode_state_t *s);
 
 /*! \brief Get the next bit of the current image. The image will
            be padded for the current minimum scan line time. 
     \param s The T.4/T.6 context.
-    \return The next bit (i.e. 0 or 1). For the last bit of data, bit 1 is
-            set (i.e. the returned value is 2 or 3). */
+    \return The next bit (i.e. 0 or 1). SIG_STATUS_END_OF_DATA for no more data. */
 SPAN_DECLARE(int) t4_t6_encode_get_bit(t4_t6_encode_state_t *s);
 
 /*! \brief Get the next byte of the current document page. The document will
index 8bb4d035eeffebde462581b90606d5a8e0940795..5ed4940b5bf3571f7bd73463fbccb7dda7a669f2 100644 (file)
@@ -253,15 +253,13 @@ SPAN_DECLARE(int) t4_tx_end_page(t4_tx_state_t *s);
            moving forward in the buffer. The document will be padded for the
            current minimum scan line time.
     \param s The T.4 context.
-    \return The next bit (i.e. 0 or 1). For the last bit of data, bit 1 is
-            set (i.e. the returned value is 2 or 3). */
-SPAN_DECLARE(int) t4_tx_check_bit(t4_tx_state_t *s);
+    \return The next bit (i.e. 0 or 1). SIG_STATUS_END_OF_DATA for no more data. */
+SPAN_DECLARE(int) t4_tx_check_if_complete(t4_tx_state_t *s);
 
 /*! \brief Get the next bit of the current document page. The document will
            be padded for the current minimum scan line time.
     \param s The T.4 context.
-    \return The next bit (i.e. 0 or 1). For the last bit of data, bit 1 is
-            set (i.e. the returned value is 2 or 3). */
+    \return The next bit (i.e. 0 or 1). SIG_STATUS_END_OF_DATA for no more data. */
 SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s);
 
 /*! \brief Get the next byte of the current document page. The document will
index 3ad36cdfdda147ef4ca8478b4c0f462634635c6b..269ba7c6c55cc24f15e732c75da59c3f0091cf68 100644 (file)
@@ -64,8 +64,12 @@ extern "C"
 {
 #endif
 
-/*! \brief Get the next byte of the current document page. The document will
-           be padded for the current minimum scan line time.
+/*! \brief Check if we are at the end of the current document page.
+    \param s The T.85 context.
+    \return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */
+SPAN_DECLARE(int) t85_encode_check_if_complete(t85_encode_state_t *s);
+
+/*! \brief Get the next byte of the current document page.
     \param s The T.85 context.
     \return The next byte. For the last byte of data, bit 8 is
             set. In this case, one or more bits of the byte may be padded with
index cf073b9049a565c57793488ccdf2d2d6d465fb82..5109c9f0fae33f908c55ed13d49857e8abcdd500 100644 (file)
@@ -748,7 +748,7 @@ static int get_partial_ecm_page(t30_state_t *s)
     /* We filled the entire buffer */
     s->ecm_frames = 256;
     span_log(&s->logging, SPAN_LOG_FLOW, "Partial page buffer full (%d per frame)\n", s->octets_per_ecm_frame);
-    s->ecm_at_page_end = ((t4_tx_check_bit(&s->t4.tx) & 2) != 0);
+    s->ecm_at_page_end = (t4_tx_check_if_complete(&s->t4.tx) == SIG_STATUS_END_OF_DATA);
     return 256;
 }
 /*- End of function --------------------------------------------------------*/
@@ -1332,12 +1332,10 @@ static int build_dcs(t30_state_t *s)
     /* Select the compression to use. */
     switch (s->line_encoding)
     {
-#if defined(SPANDSP_SUPPORT_T42)
     case T4_COMPRESSION_ITU_T42:
         set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
         set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
         break;
-#endif
 #if defined(SPANDSP_SUPPORT_T43)
     case T4_COMPRESSION_ITU_T43:
         set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE);
index 86972c0fee7a4e9f3fc24fa8c24f9272e8b97607..495ba6f9b19bbf81a27c43da4d682d92295ced3a 100644 (file)
@@ -697,9 +697,7 @@ SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_c
     mask = T30_SUPPORT_T4_1D_COMPRESSION
          | T30_SUPPORT_T4_2D_COMPRESSION
          | T30_SUPPORT_T6_COMPRESSION
-#if defined(SPANDSP_SUPPORT_T42)
-         //| T30_SUPPORT_T42_COMPRESSION
-#endif
+         //| T30_SUPPORT_T81_COMPRESSION
 #if defined(SPANDSP_SUPPORT_T43)
          | T30_SUPPORT_T43_COMPRESSION
 #endif
index a9eb7afc9c90196006461576780a0beca7084684..fd3dfcfb1a801ca4fef75ddb67c3626c3b61fcb2 100644 (file)
 #include "config.h"
 #endif
 
-#include <inttypes.h>
 #include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <memory.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 <tiffio.h>
+#include <assert.h>
 #include <jpeglib.h>
 #include <setjmp.h>
 
 #include "spandsp/telephony.h"
+#include "spandsp/fast_convert.h"
 #include "spandsp/logging.h"
+#include "spandsp/saturated.h"
 #include "spandsp/async.h"
 #include "spandsp/timezone.h"
 #include "spandsp/t4_rx.h"
@@ -362,15 +370,10 @@ static __inline__ void itu_to_lab(lab_params_t *s, cielab_t *lab, const uint8_t
 
 static __inline__ void lab_to_itu(lab_params_t *s, uint8_t out[3], const cielab_t *lab)
 {
-    float val;
-
     /* T.4 E.6.4 */
-    val = floorf(lab->L/s->range_L + s->offset_L);
-    out[0] = (uint8_t) (val < 0.0)  ?  0  :  (val < 256.0)  ?  val  :  255;
-    val = floorf(lab->a/s->range_a + s->offset_a);
-    out[1] = (uint8_t) (val < 0.0)  ?  0  :  (val < 256.0)  ?  val  :  255;
-    val = floorf(lab->b/s->range_b + s->offset_b);
-    out[2] = (uint8_t) (val < 0.0)  ?  0  :  (val < 256.0)  ?  val  :  255;
+    out[0] = saturateu8(floorf(lab->L/s->range_L + s->offset_L));
+    out[1] = saturateu8(floorf(lab->a/s->range_a + s->offset_a));
+    out[2] = saturateu8(floorf(lab->b/s->range_b + s->offset_b));
     if (s->ab_are_signed)
     {
         out[1] -= 128;
@@ -485,13 +488,9 @@ SPAN_DECLARE(void) lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t la
         g = (g > 0.0031308f)  ?  (1.055f*powf(g, 1.0f/2.4f) - 0.055f)  :  g*12.92f;
         b = (b > 0.0031308f)  ?  (1.055f*powf(b, 1.0f/2.4f) - 0.055f)  :  b*12.92f;
 
-        r = floorf(r*256.0f);
-        g = floorf(g*256.0f);
-        b = floorf(b*256.0f);
-
-        srgb[0] = (r < 0)  ?  0  :  (r <= 255)  ?  r  :  255;
-        srgb[1] = (g < 0)  ?  0  :  (g <= 255)  ?  g  :  255;
-        srgb[2] = (b < 0)  ?  0  :  (b <= 255)  ?  b  :  255;
+        srgb[0] = saturateu8(floorf(r*256.0f));
+        srgb[1] = saturateu8(floorf(g*256.0f));
+        srgb[2] = saturateu8(floorf(b*256.0f));
 #endif
         srgb += 3;
         lab += 3;
@@ -929,7 +928,7 @@ SPAN_DECLARE(int) t42_srgb_to_itulab(logging_state_t *logging, lab_params_t *s,
 
     for (pos = 0;  pos < srclen;  pos += compressor.image_width*compressor.num_components)
     {
-        scan_line_in = (JSAMPROW)src + pos;
+        scan_line_in = (JSAMPROW) src + pos;
         srgb_to_lab(s, scan_line_out, scan_line_in, compressor.image_width);
         jpeg_write_scanlines(&compressor, &scan_line_out, 1);
     }
@@ -1033,7 +1032,7 @@ SPAN_DECLARE(int) t42_itulab_to_itulab(logging_state_t *logging, tdata_t *dst, t
 
     for (pos = 0;  pos < srclen;  pos += compressor.image_width*compressor.num_components)
     {
-        scan_line_in = (JSAMPROW)src + pos;
+        scan_line_in = (JSAMPROW) src + pos;
         jpeg_write_scanlines(&compressor, &scan_line_in, 1);
     }
 
@@ -1150,7 +1149,7 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s,
 
     for (pos = 0;  decompressor.output_scanline < decompressor.output_height;  pos += decompressor.output_width*decompressor.num_components)
     {
-        scan_line_out = (JSAMPROW)dst + pos;
+        scan_line_out = (JSAMPROW) dst + pos;
         jpeg_read_scanlines(&decompressor, &scan_line_in, 1);
         lab_to_srgb(s, scan_line_out, scan_line_in, decompressor.output_width);
     }
@@ -1196,6 +1195,12 @@ SPAN_DECLARE(void) t42_encode_comment(t42_encode_state_t *s, const uint8_t comme
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) t42_encode_check_if_complete(t42_encode_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(int) t42_encode_get_byte(t42_encode_state_t *s)
 {
     return 0;
index 49f059e89c8b834c3c61e1f27654c0a9a729b235..89f10664e443db5b637c4bcdddc9f102905f208a 100644 (file)
@@ -900,9 +900,25 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(int) t4_tx_check_bit(t4_tx_state_t *s)
+SPAN_DECLARE(int) t4_tx_check_if_complete(t4_tx_state_t *s)
 {
-    return t4_t6_encode_check_bit(&s->encoder.t4_t6);
+    switch (s->line_encoding)
+    {
+    case T4_COMPRESSION_ITU_T4_1D:
+    case T4_COMPRESSION_ITU_T4_2D:
+    case T4_COMPRESSION_ITU_T6:
+        return t4_t6_encode_check_bit(&s->encoder.t4_t6);
+    case T4_COMPRESSION_ITU_T42:
+        return t42_encode_check_if_complete(&s->encoder.t42);
+#if defined(SPANDSP_SUPPORT_T43)
+    case T4_COMPRESSION_ITU_T43:
+        return t43_encode_check_if_complete(&s->encoder.t43);
+#endif
+    case T4_COMPRESSION_ITU_T85:
+    case T4_COMPRESSION_ITU_T85_L0:
+        return t85_encode_check_if_complete(&s->encoder.t85);
+    }
+    return SIG_STATUS_END_OF_DATA;
 }
 /*- End of function --------------------------------------------------------*/
 
index 6bcb3441f5c4cb26487443373d9c5e6bb28cd586..c82609c19fae62175a81b9336f51e27f47915fc3 100644 (file)
@@ -36,6 +36,7 @@
 
 #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"
@@ -580,6 +581,14 @@ SPAN_DECLARE(void) t85_encode_comment(t85_encode_state_t *s, const uint8_t comme
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) t85_encode_check_if_complete(t85_encode_state_t *s)
+{
+    if (s->y >= s->yd)
+        return SIG_STATUS_END_OF_DATA;
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(int) t85_encode_get_byte(t85_encode_state_t *s)
 {
     if (s->bitstream_optr >= s->bitstream_iptr)
index b1930c12a3edfa79d7711d16efff730937b62f82..c902ed4d52bd055c73947c900d044e512340fe7f 100644 (file)
@@ -74,60 +74,131 @@ static void display_row(int row, int width, uint8_t buf[])
 }
 /*- End of function --------------------------------------------------------*/
 
+static void create_undithered_50_by_50(image_descriptor_t *im, uint8_t buf[], int bytes_per_pixel)
+{
+    unsigned int i;
+    unsigned int j;
+    uint8_t *image8;
+    uint16_t *image16;
+
+    im->image = (const uint8_t *) buf;
+    im->width = 50;
+    im->length = 50;
+    im->bytes_per_pixel = bytes_per_pixel;
+    im->current_row = 0;
+
+    switch (bytes_per_pixel)
+    {
+    case 1:
+        image8 = buf;
+        for (i = 0;  i < 50;  i++)
+        {
+            for (j = 0;  j < 50;  j++)
+                image8[50*i + j] = ((i + j)*655) >> 8;
+        }
+        break;
+    case 2:
+        image16 = (uint16_t *) buf;
+        for (i = 0;  i < 50;  i++)
+        {
+            for (j = 0;  j < 50;  j++)
+                image16[50*i + j] = (i + j)*655;
+        }
+        break;
+    case 3:
+        image8 = buf;
+        for (i = 0;  i < 50;  i++)
+        {
+            for (j = 0;  j < 50;  j++)
+            {
+#if 1
+                image8[50*3*i + 3*j + 0] = ((i + j)*655) >> 8;
+                image8[50*3*i + 3*j + 1] = ((i + j)*655) >> 8;
+                image8[50*3*i + 3*j + 2] = ((i + j)*655) >> 8;
+#else
+                image8[50*3*i + 3*j + 0] = saturateu8((((i + j)*655U)*36532U) >> 23);
+                image8[50*3*i + 3*j + 1] = saturateu8((((i + j)*655U)*37216U) >> 24);
+                image8[50*3*i + 3*j + 2] = saturateu8((((i + j)*655U)*47900U) >> 22);
+#endif
+            }
+        }
+        break;
+    case 6:
+        image16 = (uint16_t *) buf;
+        for (i = 0;  i < 50;  i++)
+        {
+            for (j = 0;  j < 50;  j++)
+            {
+#if 1
+                image16[50*3*i + 3*j + 0] = (i + j)*655;
+                image16[50*3*i + 3*j + 1] = (i + j)*655;
+                image16[50*3*i + 3*j + 2] = (i + j)*655;
+#else
+                image16[50*3*i + 3*j + 0] = saturateu16((((i + j)*655U)*36532U) >> 15);
+                image16[50*3*i + 3*j + 1] = saturateu16((((i + j)*655U)*37216U) >> 16);
+                image16[50*3*i + 3*j + 2] = saturateu16((((i + j)*655U)*47900U) >> 14);
+#endif
+            }
+        }
+        break;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
 static int test_dithered_50_by_50(int row, int width, uint8_t buf[])
 {
     static const char *image[50] =
     {
-        "  0:                  @  @  @ @ @ @ @ @@ @@@@@@@@@@@@@@",
-        "  1:             @ @ @  @  @ @ @ @ @ @@ @@ @ @ @ @ @@@@",
-        "  2:        @ @       @  @  @  @ @ @@ @ @ @@@ @@@@@@ @@",
-        "  3:              @ @  @  @ @ @ @ @ @ @ @@@ @@@@ @@@@@@",
-        "  4:      @    @     @  @  @ @ @ @ @ @@@ @ @@ @@@@ @@@@",
-        "  5:         @   @ @  @  @ @  @ @ @ @ @ @ @@ @@@ @@@@@@",
-        "  6:                 @  @  @ @ @ @ @@ @@@@ @@@ @@@ @@ @",
-        "  7:           @ @ @   @  @  @ @ @ @ @@  @@ @ @@ @@@@@@",
-        "  8:      @         @   @  @ @  @ @ @ @@@ @@@@@@@@@ @@@",
-        "  9:        @  @  @  @ @ @ @ @ @ @ @ @ @ @@ @ @ @ @@@@@",
-        " 10:                @    @  @ @ @ @@ @ @@ @@@@@@@@@@@@@",
-        " 11:            @ @   @ @  @ @ @ @ @ @@ @@ @ @ @@ @@ @@",
-        " 12:      @  @      @   @ @   @ @ @ @ @@ @@@@@@ @@@@@@@",
-        " 13:           @  @  @ @   @ @ @ @ @@ @ @ @ @ @@@@@ @@@",
-        " 14:                @   @ @ @ @ @ @ @@ @@@ @@@ @ @@@@@@",
-        " 15:         @  @ @   @ @  @  @ @ @ @ @ @ @@ @@@@@@@ @@",
-        " 16:     @          @    @  @ @ @ @ @ @@ @@ @@ @@ @@@@@",
-        " 17:           @  @   @ @ @ @ @ @ @ @@ @@ @@ @@ @@@@@@@",
-        " 18:       @     @  @  @  @  @ @ @ @ @ @ @@ @@@@@ @ @@@",
-        " 19:           @     @   @  @ @ @ @ @ @@@ @@@ @ @@@@@@@",
-        " 20:         @   @ @  @ @ @ @  @ @ @@ @ @@ @@@@@@ @@@ @",
-        " 21:      @         @      @  @ @ @ @ @@ @@ @ @ @@@@@@@",
-        " 22:          @  @   @ @ @  @@ @ @ @ @ @@ @@@@@@@ @@ @@",
-        " 23:        @      @  @  @ @   @ @ @@ @@ @@ @ @ @@@@@@@",
-        " 24:           @     @  @  @ @@ @ @ @@ @ @ @@@@@@ @@@@@",
-        " 25:             @ @  @  @ @ @  @ @ @ @ @@@@@ @ @@@@ @@",
-        " 26:     @  @        @  @   @ @ @ @ @ @@ @ @ @@@@ @@@@@",
-        " 27:           @ @ @  @  @ @  @ @ @ @@ @ @@ @@@ @@@@@@@",
-        " 28:                 @  @ @ @ @ @ @ @ @@@ @@@ @@@ @@ @@",
-        " 29:         @  @  @  @  @   @ @ @ @@ @ @@ @ @@ @@@@@@@",
-        " 30:      @       @    @  @ @ @ @ @ @ @ @ @@@@@@@ @@@@@",
-        " 31:            @    @  @ @ @  @ @ @ @ @@@@ @ @ @@@@ @@",
-        " 32:        @  @  @ @  @   @ @ @ @ @@ @ @ @@@@@@@ @@@@@",
-        " 33:                 @  @ @  @ @ @ @ @@@ @@ @ @ @@@@@@@",
-        " 34:     @   @  @  @   @  @ @ @ @ @ @ @ @@ @@@@@@ @ @@@",
-        " 35:             @    @  @  @  @ @ @ @ @ @@ @ @ @@@@@@@",
-        " 36:          @    @ @  @  @ @ @ @ @@ @@@ @@@@@@@ @@@ @",
-        " 37:        @    @     @  @  @ @ @ @ @ @ @@ @ @ @@@@@@@",
-        " 38:               @ @  @ @ @ @ @ @ @@ @@ @@@@@@@ @@ @@",
-        " 39:      @   @ @ @    @   @  @ @ @ @ @@ @@ @ @ @@@@@@@",
-        " 40:                @ @  @ @ @ @ @ @ @ @@ @@ @@@@ @@@@@",
-        " 41:        @   @  @   @ @  @ @ @ @ @@ @ @@ @@@ @@@@ @@",
-        " 42:              @  @   @ @  @ @ @@ @@ @@ @@ @@@ @@@@@",
-        " 43:         @  @      @  @  @ @ @ @ @ @ @@ @@@ @@@@@@@",
-        " 44:     @        @ @ @  @ @ @  @ @ @ @@@ @@@ @@@ @@ @@",
-        " 45:            @       @   @ @ @ @ @@ @ @ @ @@ @@@@@@@",
-        " 46:       @  @   @ @ @  @ @ @ @ @ @ @@ @@@@@@@@@ @@@@@",
-        " 47:            @    @  @ @ @  @ @ @ @ @@ @ @ @ @@@@ @@",
-        " 48:              @   @    @ @ @ @ @@ @ @@ @@@@@@ @@@@@",
-        " 49:     @   @  @   @  @ @ @  @ @ @ @ @@ @@ @ @ @@@@@@@"
+        "  0:                               @   @  @  @ @ @ @ @ ",
+        "  1:                @   @  @ @ @ @  @ @  @  @  @  @ @ @",
+        "  2:           @      @   @     @  @   @  @ @ @ @ @ @ @",
+        "  3:               @    @    @ @  @  @ @ @ @ @ @ @ @ @ ",
+        "  4:       @  @  @   @    @      @  @   @  @  @ @ @ @ @",
+        "  5:                    @  @ @ @  @  @ @  @ @ @  @ @ @ ",
+        "  6:    @      @  @  @       @  @  @  @ @ @  @ @ @ @ @@",
+        "  7:         @     @   @ @ @  @  @  @ @  @ @ @ @ @ @ @ ",
+        "  8:      @     @    @    @  @  @ @  @ @ @ @ @ @ @ @ @ ",
+        "  9:   @      @    @    @   @  @   @ @  @ @ @ @ @ @ @ @",
+        " 10:      @     @    @ @  @  @  @ @  @ @  @ @ @ @ @@ @@",
+        " 11:          @   @ @    @  @  @  @ @ @ @ @ @ @ @ @ @@ ",
+        " 12:   @  @ @        @ @  @  @ @ @  @  @ @ @ @ @@ @ @ @",
+        " 13:           @ @ @    @  @  @  @ @ @ @ @ @ @ @ @ @@ @",
+        " 14:   @   @        @ @  @  @  @  @ @ @ @ @ @ @ @@ @ @@",
+        " 15:     @   @ @ @ @    @  @ @ @ @ @ @ @ @ @ @ @@ @ @@ ",
+        " 16:                @ @  @  @  @ @  @ @ @ @ @@ @ @@@ @@",
+        " 17:   @  @ @ @ @ @  @  @  @  @ @ @ @ @ @ @ @ @ @ @ @ @",
+        " 18:     @       @  @  @ @ @ @  @ @ @ @ @ @@ @@ @@ @@@ ",
+        " 19: @ @     @ @  @  @ @  @  @ @ @ @ @ @ @ @ @ @ @@ @ @",
+        " 20:     @ @   @   @   @ @ @ @ @  @ @ @ @@ @@ @@@ @@@@@",
+        " 21:   @     @  @ @ @ @  @  @ @ @@ @ @ @ @ @ @ @ @@ @ @",
+        " 22:    @ @ @  @    @  @  @ @  @  @ @ @@ @@ @@@ @ @@ @@",
+        " 23:  @       @  @ @  @ @ @ @ @ @@ @ @ @ @ @ @ @@@ @@ @",
+        " 24:   @ @ @ @  @ @ @ @ @ @ @ @ @ @ @@ @@ @@@ @ @ @@ @@",
+        " 25: @    @   @  @   @  @  @ @ @ @ @ @ @ @ @ @@@@@ @@@@",
+        " 26:   @   @ @  @ @ @ @ @ @ @ @ @ @@ @@ @@@ @ @ @@@ @ @",
+        " 27: @  @ @   @  @  @  @ @ @ @ @ @ @ @ @ @ @@@ @@ @@@@@",
+        " 28:   @   @ @  @ @ @ @ @ @ @ @ @ @ @@ @@ @ @ @@ @@ @ @",
+        " 29: @  @ @   @ @  @  @ @ @ @ @ @@ @@ @@ @@@@@ @@@ @@@@",
+        " 30:   @   @ @  @ @ @ @ @ @ @ @@ @@ @ @ @@ @ @@@ @@@ @@",
+        " 31: @  @ @ @  @ @ @ @ @ @ @ @ @ @ @@ @@@ @ @@ @@@ @@@@",
+        " 32:   @   @ @  @  @ @ @ @ @ @ @ @ @ @@ @@@@@ @@ @@@ @@",
+        " 33: @  @ @  @ @ @ @ @ @ @ @ @@ @@@ @@ @ @ @ @@@@@ @@@@",
+        " 34:  @  @ @  @ @ @ @ @ @ @@ @ @ @ @@ @@@@@@@ @ @@@@ @@",
+        " 35:   @  @  @ @  @ @ @ @ @ @@ @@ @@ @@ @ @ @@@@@@ @@@@",
+        " 36:  @ @  @ @ @ @ @ @ @ @ @ @@ @@ @@ @@@ @@ @ @@@@@@ @",
+        " 37:  @  @ @ @ @ @ @ @ @@ @@ @ @ @@ @@ @ @@@@@@@ @@ @@@",
+        " 38:  @ @ @ @ @ @ @ @ @ @ @ @@@ @@ @@ @@@@ @ @@@@@@@@@@",
+        " 39:   @  @  @  @ @ @ @ @@ @@ @@ @@ @@@@ @@@@ @@ @@ @@@",
+        " 40: @  @ @ @ @@ @ @ @@ @ @ @ @ @@ @@ @ @@ @@@@@@@@@@@@",
+        " 41: @ @ @ @ @  @ @ @@ @ @@@ @@@ @@@ @@@@@@@@@ @@ @@ @@",
+        " 42:  @ @ @ @ @@ @ @ @ @@ @ @@ @@ @@@@ @ @ @@@@@@@@@@@@",
+        " 43: @ @  @ @ @ @ @@ @@ @ @@ @@ @@@ @ @@@@@@@ @@ @@@@@@",
+        " 44:  @ @ @ @ @ @ @ @ @@ @@ @@ @@ @@@@@ @@ @@@@@@@@ @@@",
+        " 45: @ @ @ @ @ @ @@ @@ @@ @@ @@ @@@ @ @@@@@@@@ @@@@@@@@",
+        " 46:  @ @ @ @ @ @ @@ @ @ @@ @@ @@ @@@@@ @ @@ @@@@@@@@@@",
+        " 47: @ @ @ @ @ @@ @ @ @@@@ @@@@ @@@@@ @@@@@@@@@@@ @@@@@",
+        " 48:  @ @ @ @@ @ @@ @@ @ @@ @ @@@ @ @@@@@ @@@@@@@@@@@@@",
+        " 49: @ @ @ @ @ @@ @@ @@ @@ @@@@ @@@@@@@ @@@@@@ @@@@@@@@" 
     };
     int i;
     int match;
@@ -193,8 +264,8 @@ static void get_bilevel_image(image_translate_state_t *s, int compare)
 
 static void get_gray8_image(image_translate_state_t *s, int compare)
 {
-    int i;
-    int j;
+    unsigned int i;
+    unsigned int j;
     int len;
     uint8_t row_buf[5000];
 
@@ -209,9 +280,9 @@ static void get_gray8_image(image_translate_state_t *s, int compare)
         {
             for (j = 0;  j < 50;  j++)
             {
-                if (row_buf[j] != j*1200/256)
+                if (row_buf[j] != (((i + j)*655) >> 8))
                 {
-                    printf("Image mismatch - %d - %d\n", j, row_buf[3*j]);
+                    printf("Image mismatch - %dx%d - %d %d\n", j, i, ((i + j)*655) >> 8, row_buf[j]);
                     exit(2);
                 }
             }
@@ -227,8 +298,8 @@ static void get_gray8_image(image_translate_state_t *s, int compare)
 
 static void get_gray16_image(image_translate_state_t *s, int compare)
 {
-    int i;
-    int j;
+    unsigned int i;
+    unsigned int j;
     int len;
     uint16_t row_buf[5000];
 
@@ -243,9 +314,9 @@ static void get_gray16_image(image_translate_state_t *s, int compare)
         {
             for (j = 0;  j < 50;  j++)
             {
-                if (row_buf[j] != j*1200)
+                if (row_buf[j] != (i + j)*655)
                 {
-                    printf("Image mismatch - %d - %d\n", j, row_buf[j]);
+                    printf("Image mismatch - %dx%d - %d %d\n", j, i, (i + j)*655, row_buf[j]);
                     exit(2);
                 }
             }
@@ -261,9 +332,12 @@ static void get_gray16_image(image_translate_state_t *s, int compare)
 
 static void get_colour8_image(image_translate_state_t *s, int compare)
 {
-    int i;
-    int j;
+    unsigned int i;
+    unsigned int j;
     int len;
+    int r;
+    int g;
+    int b;
     uint8_t row_buf[5000];
 
     for (i = 0;  i < s->output_length;  i++)
@@ -277,9 +351,21 @@ static void get_colour8_image(image_translate_state_t *s, int compare)
         {
             for (j = 0;  j < 50;  j++)
             {
-                if (row_buf[3*j + 0] != j*1200/256  ||  row_buf[3*j + 1] != j*1200/256  ||  row_buf[3*j + 2] != j*1200/256)
+#if 1
+                r = ((i + j)*655) >> 8;
+                g = ((i + j)*655) >> 8;
+                b = ((i + j)*655) >> 8;
+#else
+                r = saturateu8((((i + j)*655U)*36532U) >> 23);
+                g = saturateu8((((i + j)*655U)*37216U) >> 24);
+                b = saturateu8((((i + j)*655U)*47900U) >> 22);
+#endif
+                if (row_buf[3*j + 0] != r  ||  row_buf[3*j + 1] != g  ||  row_buf[3*j + 2] != b)
                 {
-                    printf("Image mismatch - %d - %d %d %d\n", j, row_buf[3*j + 0], row_buf[3*j + 1], row_buf[3*j + 2]);
+                    printf("Image mismatch - %dx%d - (%d %d %d) (%d %d %d)\n",
+                           j, i,
+                           r, g, b,
+                           row_buf[3*j + 0], row_buf[3*j + 1], row_buf[3*j + 2]);
                     exit(2);
                 }
             }
@@ -295,9 +381,12 @@ static void get_colour8_image(image_translate_state_t *s, int compare)
 
 static void get_colour16_image(image_translate_state_t *s, int compare)
 {
-    int i;
-    int j;
+    unsigned int i;
+    unsigned int j;
     int len;
+    int r;
+    int g;
+    int b;
     uint16_t row_buf[5000];
 
     for (i = 0;  i < s->output_length;  i++)
@@ -311,9 +400,21 @@ static void get_colour16_image(image_translate_state_t *s, int compare)
         {
             for (j = 0;  j < 50;  j++)
             {
-                if (row_buf[3*j + 0] != j*1200  ||  row_buf[3*j + 1] != j*1200  ||  row_buf[3*j + 2] != j*1200)
+#if 1
+                r = (i + j)*655;
+                g = (i + j)*655;
+                b = (i + j)*655;
+#else
+                r = saturateu16((((i + j)*655U)*36532U) >> 15);
+                g = saturateu16((((i + j)*655U)*37216U) >> 16);
+                b = saturateu16((((i + j)*655U)*47900U) >> 14);
+#endif
+                if (row_buf[3*j + 0] != r  ||  row_buf[3*j + 1] != g  ||  row_buf[3*j + 2] != b)
                 {
-                    printf("Image mismatch - %d - %d %d %d\n", j, row_buf[3*j + 0], row_buf[3*j + 1], row_buf[3*j + 2]);
+                    printf("Image mismatch - %dx%d - (%d %d %d) (%d %d %d)\n",
+                           j, i,
+                           r, g, b,
+                           row_buf[3*j + 0], row_buf[3*j + 1], row_buf[3*j + 2]);
                     exit(2);
                 }
             }
@@ -327,165 +428,104 @@ static void get_colour16_image(image_translate_state_t *s, int compare)
 }
 /*- End of function --------------------------------------------------------*/
 
-static void dither_tests_gray16(void)
+static void translate_tests_gray16(void)
 {
-    int i;
-    int j;
     image_translate_state_t *s;
     uint16_t image[50*50];
     image_descriptor_t im;
 
     printf("Dithering from a 16 bit per sample gray scale to bi-level\n");
-    im.image = (const uint8_t *) image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 2;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-            image[i*im.width + j] = j*1200;
-    }
-
+    create_undithered_50_by_50(&im, (uint8_t *) image, 2);
     s = image_translate_init(NULL, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im);
     get_bilevel_image(s, TRUE);
+
+    printf("Scrunching from a 16 bit per sample gray scale to 8 bit per sample gray scale\n");
+    create_undithered_50_by_50(&im, (uint8_t *) image, 2);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, row_read, &im);
+    get_gray8_image(s, TRUE);
+
+    printf("Scrunching from a 16 bit per sample gray scale to 16 bit per sample gray scale\n");
+    create_undithered_50_by_50(&im, (uint8_t *) image, 2);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, row_read, &im);
+    get_gray16_image(s, TRUE);
+
+    printf("Scrunching from a 16 bit per sample gray scale to 3x8 bit per sample colour\n");
+    create_undithered_50_by_50(&im, (uint8_t *) image, 2);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, row_read, &im);
+    get_colour8_image(s, TRUE);
+
+    printf("Scrunching from a 16 bit per sample gray scale to 3x16 bit per sample colour\n");
+    create_undithered_50_by_50(&im, (uint8_t *) image, 2);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, row_read, &im);
+    get_colour16_image(s, TRUE);
+
     image_translate_free(s);
 }
 /*- End of function --------------------------------------------------------*/
 
-static void dither_tests_gray8(void)
+static void translate_tests_gray8(void)
 {
-    int i;
-    int j;
     image_translate_state_t *s;
     uint8_t image[50*50];
     image_descriptor_t im;
 
     printf("Dithering from a 8 bit per sample gray scale to bi-level\n");
-    im.image = image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 1;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-            image[i*im.width + j] = j*1200/256;
-    }
-
+    create_undithered_50_by_50(&im, image, 1);
     s = image_translate_init(NULL, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im);
     get_bilevel_image(s, TRUE);
+
+    printf("Scrunching from a 8 bit per sample gray scale to 8 bit per sample gray scale\n");
+    create_undithered_50_by_50(&im, image, 1);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, row_read, &im);
+    get_gray8_image(s, TRUE);
+
+    printf("Scrunching from a 8 bit per sample gray scale to 16 bit per sample gray scale\n");
+    create_undithered_50_by_50(&im, image, 1);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, row_read, &im);
+    get_gray16_image(s, TRUE);
+
+    printf("Scrunching from a 8 bit per sample gray scale to 3x8 bit per sample colour\n");
+    create_undithered_50_by_50(&im, image, 1);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, row_read, &im);
+    get_colour8_image(s, TRUE);
+
+    printf("Scrunching from a 8 bit per sample gray scale to 3x16 bit per sample colour\n");
+    create_undithered_50_by_50(&im, image, 1);
+    s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, row_read, &im);
+    get_colour16_image(s, TRUE);
+
     image_translate_free(s);
 }
 /*- End of function --------------------------------------------------------*/
 
-static void dither_tests_colour16(void)
+static void translate_tests_colour16(void)
 {
-    int i;
-    int j;
     image_translate_state_t *s;
     uint16_t image[50*50*3];
     image_descriptor_t im;
 
     printf("Dithering from a 3x16 bit per sample colour to bi-level\n");
-    im.image = (const uint8_t *) image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 6;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-        {
-            image[i*3*im.width + 3*j + 0] = j*1200 + i;
-            image[i*3*im.width + 3*j + 1] = j*1200 + i;
-            image[i*3*im.width + 3*j + 2] = j*1200 + i;
-        }
-    }
-
+    create_undithered_50_by_50(&im, (uint8_t *) image, 6);
     s = image_translate_init(NULL, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im);
     get_bilevel_image(s, TRUE);
 
     printf("Scrunching from a 3x16 bit per sample colour to 8 bit per sample gray scale\n");
-    im.image = (const uint8_t *) image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 6;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-        {
-            image[i*3*im.width + 3*j + 0] = j*1200 + i;
-            image[i*3*im.width + 3*j + 1] = j*1200 + i;
-            image[i*3*im.width + 3*j + 2] = j*1200 + i;
-        }
-    }
-
+    create_undithered_50_by_50(&im, (uint8_t *) image, 6);
     s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, row_read, &im);
     get_gray8_image(s, TRUE);
 
     printf("Scrunching from a 3x16 bit per sample colour to 16 bit per sample gray scale\n");
-    im.image = (const uint8_t *) image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 6;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-        {
-            image[i*3*im.width + 3*j + 0] = j*1200 + i;
-            image[i*3*im.width + 3*j + 1] = j*1200 + i;
-            image[i*3*im.width + 3*j + 2] = j*1200 + i;
-        }
-    }
-
+    create_undithered_50_by_50(&im, (uint8_t *) image, 6);
     s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, row_read, &im);
     get_gray16_image(s, TRUE);
 
     printf("Scrunching from a 3x16 bit per sample colour to 3x8 bit per sample colour\n");
-    im.image = (const uint8_t *) image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 6;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-        {
-            image[i*3*im.width + 3*j + 0] = j*1200 + i;
-            image[i*3*im.width + 3*j + 1] = j*1200 + i;
-            image[i*3*im.width + 3*j + 2] = j*1200 + i;
-        }
-    }
-
+    create_undithered_50_by_50(&im, (uint8_t *) image, 6);
     s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, row_read, &im);
     get_colour8_image(s, TRUE);
 
     printf("Scrunching from a 3x16 bit per sample colour to 3x16 bit per sample colour\n");
-    im.image = (const uint8_t *) image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 6;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-        {
-            image[i*3*im.width + 3*j + 0] = j*1200 + i;
-            image[i*3*im.width + 3*j + 1] = j*1200 + i;
-            image[i*3*im.width + 3*j + 2] = j*1200 + i;
-        }
-    }
-
+    create_undithered_50_by_50(&im, (uint8_t *) image, 6);
     s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, row_read, &im);
     get_colour16_image(s, TRUE);
 
@@ -493,61 +533,49 @@ static void dither_tests_colour16(void)
 }
 /*- End of function --------------------------------------------------------*/
 
-static void dither_tests_colour8(void)
+static void translate_tests_colour8(void)
 {
-    int i;
-    int j;
     image_translate_state_t *s;
     uint8_t image[50*50*3];
     image_descriptor_t im;
 
     printf("Dithering from a 3x8 bit per sample colour to bi-level\n");
-    im.image = image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 3;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-        {
-            image[i*3*im.width + 3*j + 0] = j*1200/256 + i;
-            image[i*3*im.width + 3*j + 1] = j*1200/256 + i;
-            image[i*3*im.width + 3*j + 2] = j*1200/256 + i;
-        }
-    }
-
+    create_undithered_50_by_50(&im, image, 3);
     s = image_translate_init(NULL, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im);
     get_bilevel_image(s, TRUE);
+
+    printf("Scrunching from a 3x8 bit per sample colour to 8 bit per sample gray scale\n");
+    create_undithered_50_by_50(&im, image, 3);
+    s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, row_read, &im);
+    get_gray8_image(s, TRUE);
+
+    printf("Scrunching from a 3x8 bit per sample colour to 16 bit per sample gray scale\n");
+    create_undithered_50_by_50(&im, image, 3);
+    s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, row_read, &im);
+    get_gray16_image(s, TRUE);
+
+    printf("Scrunching from a 3x8 bit per sample colour to 3x8 bit per sample colour\n");
+    create_undithered_50_by_50(&im, image, 3);
+    s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, row_read, &im);
+    get_colour8_image(s, TRUE);
+
+    printf("Scrunching from a 3x8 bit per sample colour to 3x16 bit per sample colour\n");
+    create_undithered_50_by_50(&im, image, 3);
+    s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, row_read, &im);
+    get_colour16_image(s, TRUE);
+
     image_translate_free(s);
 }
 /*- End of function --------------------------------------------------------*/
 
 static void grow_tests_colour8(void)
 {
-    int i;
-    int j;
     image_translate_state_t *s;
     uint8_t image[50*50*3];
     image_descriptor_t im;
 
     printf("Image growth tests\n");
-    im.image = image;
-    im.width = 50;
-    im.length = 50;
-    im.bytes_per_pixel = 3;
-    im.current_row = 0;
-
-    for (i = 0;  i < im.length;  i++)
-    {
-        for (j = 0;  j < im.width;  j++)
-        {
-            image[i*3*im.width + 3*j + 0] = j*1200/256 + i;
-            image[i*3*im.width + 3*j + 1] = j*1200/256 + i;
-            image[i*3*im.width + 3*j + 2] = j*1200/256 + i;
-        }
-    }
+    create_undithered_50_by_50(&im, image, 3);
 
     s = image_translate_init(NULL, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, 200, -1, row_read, &im);
     get_bilevel_image(s, FALSE);
@@ -669,10 +697,10 @@ static void lenna_tests(int output_width, int output_length_scaling, const char
 int main(int argc, char **argv)
 {
 #if 1
-    dither_tests_gray16();
-    dither_tests_gray8();
-    dither_tests_colour16();
-    dither_tests_colour8();
+    translate_tests_gray16();
+    translate_tests_gray8();
+    translate_tests_colour16();
+    translate_tests_colour8();
 #endif
 #if 1
     grow_tests_colour8();