From 812dacfb5cbaa9434bd5716bd8550f668246382d Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sat, 11 Aug 2012 18:32:00 +0800 Subject: [PATCH] Various little tweaks A bug in end of image handling fixed, which could mean some T.85 images would screw up. --- libs/spandsp/INSTALL | 397 +++++++++++------- libs/spandsp/src/image_translate.c | 30 +- libs/spandsp/src/spandsp/t42.h | 5 + libs/spandsp/src/spandsp/t4_t6_encode.h | 6 +- libs/spandsp/src/spandsp/t4_tx.h | 8 +- libs/spandsp/src/spandsp/t85.h | 8 +- libs/spandsp/src/t30.c | 4 +- libs/spandsp/src/t30_api.c | 4 +- libs/spandsp/src/t42.c | 47 ++- libs/spandsp/src/t4_tx.c | 20 +- libs/spandsp/src/t85_encode.c | 9 + libs/spandsp/tests/image_translate_tests.c | 466 +++++++++++---------- 12 files changed, 592 insertions(+), 412 deletions(-) diff --git a/libs/spandsp/INSTALL b/libs/spandsp/INSTALL index 2abc70492a..a1e89e18ad 100644 --- a/libs/spandsp/INSTALL +++ b/libs/spandsp/INSTALL @@ -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-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. + 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 `' 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,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. -`--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 +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. diff --git a/libs/spandsp/src/image_translate.c b/libs/spandsp/src/image_translate.c index 4ee2c211bf..7ea32099ae 100644 --- a/libs/spandsp/src/image_translate.c +++ b/libs/spandsp/src/image_translate.c @@ -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); } } diff --git a/libs/spandsp/src/spandsp/t42.h b/libs/spandsp/src/spandsp/t42.h index e072b07442..a1441c0406 100644 --- a/libs/spandsp/src/spandsp/t42.h +++ b/libs/spandsp/src/spandsp/t42.h @@ -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); diff --git a/libs/spandsp/src/spandsp/t4_t6_encode.h b/libs/spandsp/src/spandsp/t4_t6_encode.h index 975b68ce21..6e30cb71f6 100644 --- a/libs/spandsp/src/spandsp/t4_t6_encode.h +++ b/libs/spandsp/src/spandsp/t4_t6_encode.h @@ -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 diff --git a/libs/spandsp/src/spandsp/t4_tx.h b/libs/spandsp/src/spandsp/t4_tx.h index 8bb4d035ee..5ed4940b5b 100644 --- a/libs/spandsp/src/spandsp/t4_tx.h +++ b/libs/spandsp/src/spandsp/t4_tx.h @@ -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 diff --git a/libs/spandsp/src/spandsp/t85.h b/libs/spandsp/src/spandsp/t85.h index 3ad36cdfdd..269ba7c6c5 100644 --- a/libs/spandsp/src/spandsp/t85.h +++ b/libs/spandsp/src/spandsp/t85.h @@ -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 diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index cf073b9049..5109c9f0fa 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -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); diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index 86972c0fee..495ba6f9b1 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -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 diff --git a/libs/spandsp/src/t42.c b/libs/spandsp/src/t42.c index a9eb7afc9c..fd3dfcfb1a 100644 --- a/libs/spandsp/src/t42.c +++ b/libs/spandsp/src/t42.c @@ -29,23 +29,31 @@ #include "config.h" #endif -#include #include +#include +#include +#include +#include +#include +#include +#include #include -#include #if defined(HAVE_TGMATH_H) #include #endif #if defined(HAVE_MATH_H) #include #endif -#include #include "floating_fudge.h" +#include +#include #include #include #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; diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 49f059e89c..89f10664e4 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -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 --------------------------------------------------------*/ diff --git a/libs/spandsp/src/t85_encode.c b/libs/spandsp/src/t85_encode.c index 6bcb3441f5..c82609c19f 100644 --- a/libs/spandsp/src/t85_encode.c +++ b/libs/spandsp/src/t85_encode.c @@ -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) diff --git a/libs/spandsp/tests/image_translate_tests.c b/libs/spandsp/tests/image_translate_tests.c index b1930c12a3..c902ed4d52 100644 --- a/libs/spandsp/tests/image_translate_tests.c +++ b/libs/spandsp/tests/image_translate_tests.c @@ -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();