diff spandsp-0.0.6pre17/tests/t4_tests.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spandsp-0.0.6pre17/tests/t4_tests.c	Fri Jun 25 15:50:58 2010 +0200
@@ -0,0 +1,696 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * t4_tests.c - ITU T.4 FAX image to and from TIFF file tests
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2003 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: t4_tests.c,v 1.69.4.1 2009/12/19 09:47:57 steveu Exp $
+ */
+
+/*! \file */
+
+/*! \page t4_tests_page T.4 tests
+\section t4_tests_page_sec_1 What does it do
+These tests exercise the image compression and decompression methods defined
+in ITU specifications T.4 and T.6.
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <memory.h>
+
+//#if defined(WITH_SPANDSP_INTERNALS)
+#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
+//#endif
+
+#include "spandsp.h"
+
+#define IN_FILE_NAME    "../test-data/itu/fax/itutests.tif"
+#define OUT_FILE_NAME   "t4_tests_receive.tif"
+
+#define XSIZE           1728
+
+t4_state_t send_state;
+t4_state_t receive_state;
+
+/* The following are some test cases from T.4 */
+#define FILL_70      "                                                                      "
+#define FILL_80      "                                                                                "
+#define FILL_100     "                                                                                                    "
+#define FILL_670     FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_70
+#define FILL_980     FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_80
+
+static const char t4_test_patterns[][1728 + 1] =
+{
+    "XXXXXX              " FILL_980 "  XXX  XXX X                  " FILL_670 "                        XXXX",
+    "XXXXXX              " FILL_980 "     XXX   X                  " FILL_670 "                        XXXX",
+    /* Line start should code to V(0). Line middle codes to VR(3) VL(2) V(0). Line end should code to V(0) V(0). */
+
+    " XXXX               " FILL_980 "    XXXXXXX                   " FILL_670 "                        XX  ",
+    "XXXXX               " FILL_980 "XX       XX                   " FILL_670 "                        XXXX",
+    /* Line start should code to VL(1). Line middle codes to H(7,2). Line end should code to V(0) VR(2) */
+
+    "XXX                 " FILL_980 " XX  XX   XX        XXX       " FILL_670 "                      X     ",
+    "                    " FILL_980 " X       XXX   XXXX           " FILL_670 "                      X   XX",
+    /* Line start should code to P. Line middle codes to P VL(1) V(0) H(3,4) P. Line end codes to V(0) VL(2) V(0). */
+
+    "XXXXX               " FILL_980 "                              " FILL_670 "                        XXXX",
+    "  XXX               " FILL_980 "                              " FILL_670 "                        XX  ",
+    /* Line start should code to VR(2). Line end codes to V(0) VL(2) V(0). */
+
+    "         XX         " FILL_980 "                              " FILL_670 "                      X  XXX",
+    "XXX       X         " FILL_980 "                              " FILL_670 "                      X     ",
+    /* Line start should code to H(0,3) VR(1). Line end codes to V(0) VR(3). */
+
+    "                    " FILL_980 "                              " FILL_670 "                         XX ",
+    "                    " FILL_980 "                              " FILL_670 "                            ",
+    /* Line end codes to P V(0) a'0. */
+
+    "                    " FILL_980 "                              " FILL_670 "                  XXXXXXXXXX",
+    "                    " FILL_980 "                              " FILL_670 "              XXXXXX  XXXXXX",
+    /* Line end codes to H(2,6). */
+
+    "                    " FILL_980 "                              " FILL_670 "                   XX  XXXXX",
+    "                    " FILL_980 "                              " FILL_670 "                   XX       ",
+    /* Line end codes to V(0) H(7,0). */
+};
+
+static void dump_image_as_xxx(t4_state_t *state)
+{
+    uint8_t *s;
+    int i;
+    int j;
+    int k;
+
+    /* Dump the entire image as text 'X's and spaces */
+    printf("Image (%d x %d):\n", receive_state.image_width, receive_state.image_length);
+    s = state->image_buffer;
+    for (i = 0;  i < state->image_length;  i++)
+    {
+        for (j = 0;  j < state->bytes_per_row;  j++)
+        {
+            for (k = 0;  k < 8;  k++)
+            {
+                printf((state->image_buffer[i*state->bytes_per_row + j] & (0x80 >> k))  ?  "X"  :  " ");
+            }
+        }
+        printf("\n");
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+static void display_page_stats(t4_state_t *s)
+{
+    t4_stats_t stats;
+
+    t4_get_transfer_statistics(s, &stats);
+    printf("Pages = %d\n", stats.pages_transferred);
+    printf("Image size = %d pels x %d pels\n", stats.width, stats.length);
+    printf("Image resolution = %d pels/m x %d pels/m\n", stats.x_resolution, stats.y_resolution);
+    printf("Bad rows = %d\n", stats.bad_rows);
+    printf("Longest bad row run = %d\n", stats.longest_bad_row_run);
+    printf("Bits per row - min %d, max %d\n", s->min_row_bits, s->max_row_bits);
+}
+/*- End of function --------------------------------------------------------*/
+
+static int row_read_handler(void *user_data, uint8_t buf[], size_t len)
+{
+    int i;
+    int j;
+    const char *s;
+    static int row = 0;
+
+    /* Send the test pattern. */
+    s = t4_test_patterns[row++];
+    if (row >= 16)
+        return 0;
+    memset(buf, 0, len);
+    for (i = 0;  i < len;  i++)
+    {
+        for (j = 0;  j < 8;  j++)
+        {
+            if (*s++ != ' ')
+                buf[i] |= (0x80 >> j);
+        }
+    }
+    if (*s)
+        printf("Oops - '%c' at end of row %d\n", *s, row);
+    return len;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int row_write_handler(void *user_data, const uint8_t buf[], size_t len)
+{
+    int i;
+    int j;
+    const char *s;
+    static int row = 0;
+    uint8_t ref[8192];
+
+    /* Verify that what is received matches the test pattern. */
+    if (len == 0)
+        return 0;
+    s = t4_test_patterns[row++];
+    if (row >= 16)
+        row = 0;
+    memset(ref, 0, len);
+    for (i = 0;  i < len;  i++)
+    {
+        for (j = 0;  j < 8;  j++)
+        {
+            if (*s++ != ' ')
+                ref[i] |= (0x80 >> j);
+        }
+    }
+    if (*s)
+        printf("Oops - '%c' at end of row %d\n", *s, row);
+    if (memcmp(buf, ref, len))
+    {
+        printf("Test failed at row %d\n", row);
+        exit(2);
+    }
+    return len;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int detect_page_end(int bit, int page_ended)
+{
+    static int consecutive_eols;
+    static int max_consecutive_eols;
+    static int consecutive_zeros;
+    static int consecutive_ones;
+    static int eol_zeros;
+    static int eol_ones;
+    static int expected_eols;
+    static int end_marks;
+
+    /* Check the EOLs are added properly to the end of an image. We can't rely on the
+       decoder giving the right answer, as a full set of EOLs is not needed for the
+       decoder to work. */
+    if (bit == -1000000)
+    {
+        /* Reset */
+        consecutive_eols = 0;
+        max_consecutive_eols = 0;
+        consecutive_zeros = 0;
+        consecutive_ones = 0;
+        end_marks = 0;
+
+        eol_zeros = 11;
+        eol_ones = (page_ended == T4_COMPRESSION_ITU_T4_2D)  ?  2  :  1;
+        expected_eols = (page_ended == T4_COMPRESSION_ITU_T6)  ?  2  :  6;
+        return FALSE;
+    }
+
+    /* Monitor whether the EOLs are there in the correct amount */
+    if (bit == 0)
+    {
+        consecutive_zeros++;
+        consecutive_ones = 0;
+    }
+    else if (bit == 1)
+    {
+        if (++consecutive_ones == eol_ones)
+        {
+            if (consecutive_eols == 0  &&  consecutive_zeros >= eol_zeros)
+                consecutive_eols++;
+            else if (consecutive_zeros == eol_zeros)
+                consecutive_eols++;
+            else
+                consecutive_eols = 0;
+            consecutive_zeros = 0;
+            consecutive_ones = 0;
+        }
+        if (max_consecutive_eols < consecutive_eols)
+            max_consecutive_eols = consecutive_eols;
+    }
+    else if (bit == SIG_STATUS_END_OF_DATA)
+    {
+        if (end_marks == 0)
+        {
+            if (max_consecutive_eols != expected_eols)
+            {
+                printf("Only %d EOLs (should be %d)\n", max_consecutive_eols, expected_eols);
+                return 2;
+            }
+            consecutive_zeros = 0;
+            consecutive_eols = 0;
+            max_consecutive_eols = 0;
+        }
+        if (!page_ended)
+        {
+            /* We might need to push a few bits to get the receiver to report the
+                end of page condition (at least with T.6). */
+            if (++end_marks > 50)
+            {
+                printf("Receiver missed the end of page mark\n");
+                return 2;
+            }
+            return 0;
+        }
+        return 1;
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+    static const int compression_sequence[] =
+    {
+        //T4_COMPRESSION_NONE,
+        T4_COMPRESSION_ITU_T4_1D,
+        T4_COMPRESSION_ITU_T4_2D,
+        T4_COMPRESSION_ITU_T6,
+        //T4_COMPRESSION_ITU_T85,
+        //T4_COMPRESSION_ITU_T43,
+        //T4_COMPRESSION_ITU_T45,
+        //T4_COMPRESSION_ITU_T81,
+        //T4_COMPRESSION_ITU_SYCC_T81
+    };
+    int sends;
+    int page_no;
+    int bit;
+    int end_of_page;
+    int end_marks;
+    int res;
+    int compression;
+    int compression_step;
+    int add_page_headers;
+    int min_row_bits;
+    int restart_pages;
+    int block_size;
+    char buf[1024];
+    uint8_t block[1024];
+    const char *in_file_name;
+    const char *decode_file_name;
+    int opt;
+    int i;
+    int bit_error_rate;
+    int dump_as_xxx;
+    int tests_failed;
+    unsigned int last_pkt_no;
+    unsigned int pkt_no;
+    int page_ended;
+    FILE *file;
+
+    tests_failed = 0;
+    compression = -1;
+    compression_step = 0;
+    add_page_headers = FALSE;
+    restart_pages = FALSE;
+    in_file_name = IN_FILE_NAME;
+    decode_file_name = NULL;
+    /* Use a non-zero default minimum row length to ensure we test the consecutive EOLs part
+       properly. */
+    min_row_bits = 50;
+    block_size = 0;
+    bit_error_rate = 0;
+    dump_as_xxx = FALSE;
+    while ((opt = getopt(argc, argv, "126b:d:ehri:m:x")) != -1)
+    {
+        switch (opt)
+        {
+        case '1':
+            compression = T4_COMPRESSION_ITU_T4_1D;
+            compression_step = -1;
+            break;
+        case '2':
+            compression = T4_COMPRESSION_ITU_T4_2D;
+            compression_step = -1;
+            break;
+        case '6':
+            compression = T4_COMPRESSION_ITU_T6;
+            compression_step = -1;
+            break;
+        case 'b':
+            block_size = atoi(optarg);
+            if (block_size > 1024)
+                block_size = 1024;
+            break;
+        case 'd':
+            decode_file_name = optarg;
+            break;
+        case 'e':
+            bit_error_rate = 0x3FF;
+            break;
+        case 'h':
+            add_page_headers = TRUE;
+            break;
+        case 'r':
+            restart_pages = TRUE;
+            break;
+        case 'i':
+            in_file_name = optarg;
+            break;
+        case 'm':
+            min_row_bits = atoi(optarg);
+            break;
+        case 'x':
+            dump_as_xxx = TRUE;
+            break;
+        default:
+            //usage();
+            exit(2);
+            break;
+        }
+    }
+    /* Create a send and a receive end */
+    memset(&send_state, 0, sizeof(send_state));
+    memset(&receive_state, 0, sizeof(receive_state));
+
+    end_of_page = FALSE;
+    if (decode_file_name)
+    {
+        if (compression < 0)
+            compression = T4_COMPRESSION_ITU_T4_1D;
+        /* Receive end puts TIFF to a new file. We assume the receive width here. */
+        if (t4_rx_init(&receive_state, OUT_FILE_NAME, T4_COMPRESSION_ITU_T4_2D) == NULL)
+        {
+            printf("Failed to init T.4 rx\n");
+            exit(2);
+        }
+        span_log_set_level(&receive_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+        t4_rx_set_rx_encoding(&receive_state, compression);
+        t4_rx_set_x_resolution(&receive_state, T4_X_RESOLUTION_R8);
+        //t4_rx_set_y_resolution(&receive_state, T4_Y_RESOLUTION_FINE);
+        t4_rx_set_y_resolution(&receive_state, T4_Y_RESOLUTION_STANDARD);
+        t4_rx_set_image_width(&receive_state, XSIZE);
+
+        page_no = 1;
+        t4_rx_start_page(&receive_state);
+        last_pkt_no = 0;
+        file = fopen(decode_file_name, "r");
+        while (fgets(buf, 1024, file))
+        {
+            if (sscanf(buf, "HDLC:  FCD: 06 %x", &pkt_no) == 1)
+            {
+                /* Useful for breaking up T.38 ECM logs */
+                for (i = 0;  i < 256;  i++)
+                {
+                    if (sscanf(&buf[18 + 3*i], "%x", (unsigned int *) &bit) != 1)
+                        break;
+                    if ((end_of_page = t4_rx_put_byte(&receive_state, bit)))
+                        break;
+                }
+            }
+            else if (sscanf(buf, "HDLC:  %x", &pkt_no) == 1)
+            {
+                /* Useful for breaking up HDLC decodes of ECM logs */
+                for (i = 0;  i < 256;  i++)
+                {
+                    if (sscanf(&buf[19 + 3*i], "%x", (unsigned int *) &bit) != 1)
+                        break;
+                    if ((end_of_page = t4_rx_put_byte(&receive_state, bit)))
+                        break;
+                }
+            }
+            else if (strlen(buf) > 62  &&  sscanf(buf + 57, "Rx %d: IFP %x %x", &pkt_no, (unsigned int *) &bit, (unsigned int *) &bit) == 3)
+            {
+                /* Useful for breaking up T.38 non-ECM logs */
+                if (pkt_no != last_pkt_no + 1)
+                    printf("Packet %u\n", pkt_no);
+                last_pkt_no = pkt_no;
+                for (i = 0;  i < 256;  i++)
+                {
+                    if (sscanf(&buf[57 + 29 + 3*i], "%x", (unsigned int *) &bit) != 1)
+                        break;
+                    bit = bit_reverse8(bit);
+                    if ((end_of_page = t4_rx_put_byte(&receive_state, bit)))
+                        break;
+                }
+            }
+            else if (sscanf(buf, "%08x  %02x %02x %02x", (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &bit) == 4)
+            {
+                for (i = 0;  i < 16;  i++)
+                {
+                    if (sscanf(&buf[10 + 3*i], "%x", (unsigned int *) &bit) != 1)
+                        break;
+                    bit = bit_reverse8(bit);
+                    if ((end_of_page = t4_rx_put_byte(&receive_state, bit)))
+                        break;
+                }
+            }
+            else if (sscanf(buf, "Rx bit %*d - %d", &bit) == 1)
+            {
+                if ((end_of_page = t4_rx_put_bit(&receive_state, bit)))
+                {
+                    printf("End of page detected\n");
+                    break;
+                }
+            }
+        }
+        fclose(file);
+        if (dump_as_xxx)
+            dump_image_as_xxx(&receive_state);
+        t4_rx_end_page(&receive_state);
+        display_page_stats(&receive_state);
+        t4_rx_release(&receive_state);
+    }
+    else
+    {
+#if 1
+        printf("Testing image_function->compress->decompress->image_function\n");
+        /* Send end gets image from a function */
+        if (t4_tx_init(&send_state, in_file_name, -1, -1) == NULL)
+        {
+            printf("Failed to init T.4 tx\n");
+            exit(2);
+        }
+        span_log_set_level(&send_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+        t4_tx_set_row_read_handler(&send_state, row_read_handler, NULL);
+        t4_tx_set_min_row_bits(&send_state, min_row_bits);
+        t4_tx_set_local_ident(&send_state, "111 2222 3333");
+
+        /* Receive end puts TIFF to a function. */
+        if (t4_rx_init(&receive_state, OUT_FILE_NAME, T4_COMPRESSION_ITU_T4_2D) == NULL)
+        {
+            printf("Failed to init T.4 rx\n");
+            exit(2);
+        }
+        span_log_set_level(&receive_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+        t4_rx_set_row_write_handler(&receive_state, row_write_handler, NULL);
+        t4_rx_set_image_width(&receive_state, t4_tx_get_image_width(&send_state));
+        t4_rx_set_x_resolution(&receive_state, t4_tx_get_x_resolution(&send_state));
+        t4_rx_set_y_resolution(&receive_state, t4_tx_get_y_resolution(&send_state));
+
+        /* Now send and receive the test data with all compression modes. */
+        page_no = 1;
+        /* If we are stepping around the compression schemes, reset to the start of the sequence. */
+        if (compression_step > 0)
+            compression_step = 0;
+        for (;;)
+        {
+            end_marks = 0;
+            if (compression_step >= 0)
+            {
+                compression = compression_sequence[compression_step++];
+                if (compression_step > 3)
+                    break;
+            }
+            t4_tx_set_tx_encoding(&send_state, compression);
+            t4_rx_set_rx_encoding(&receive_state, compression);
+
+            if (t4_tx_start_page(&send_state))
+                break;
+            t4_rx_start_page(&receive_state);
+            do
+            {
+                bit = t4_tx_get_bit(&send_state);
+                if (bit == SIG_STATUS_END_OF_DATA)
+                {
+                    if (++end_marks > 50)
+                    {
+                        printf("Receiver missed the end of page mark\n");
+                        tests_failed++;
+                        break;
+                    }
+                }
+                end_of_page = t4_rx_put_bit(&receive_state, bit & 1);
+            }
+            while (!end_of_page);
+            t4_tx_end_page(&send_state);
+            t4_rx_end_page(&receive_state);
+            if (compression_step < 0)
+                break;
+        }
+        t4_tx_release(&send_state);
+        t4_rx_release(&receive_state);
+#endif
+#if 1
+        printf("Testing TIFF->compress->decompress->TIFF cycle\n");
+        /* Send end gets TIFF from a file */
+        if (t4_tx_init(&send_state, in_file_name, -1, -1) == NULL)
+        {
+            printf("Failed to init T.4 send\n");
+            exit(2);
+        }
+        span_log_set_level(&send_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+        t4_tx_set_min_row_bits(&send_state, min_row_bits);
+        t4_tx_set_local_ident(&send_state, "111 2222 3333");
+
+        /* Receive end puts TIFF to a new file. */
+        if (t4_rx_init(&receive_state, OUT_FILE_NAME, T4_COMPRESSION_ITU_T4_2D) == NULL)
+        {
+            printf("Failed to init T.4 rx for '%s'\n", OUT_FILE_NAME);
+            exit(2);
+        }
+        span_log_set_level(&receive_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+        t4_rx_set_x_resolution(&receive_state, t4_tx_get_x_resolution(&send_state));
+        t4_rx_set_y_resolution(&receive_state, t4_tx_get_y_resolution(&send_state));
+        t4_rx_set_image_width(&receive_state, t4_tx_get_image_width(&send_state));
+
+        /* Now send and receive all the pages in the source TIFF file */
+        page_no = 1;
+        sends = 0;
+        /* If we are stepping around the compression schemes, reset to the start of the sequence. */
+        if (compression_step > 0)
+            compression_step = 0;
+        for (;;)
+        {
+            end_marks = 0;
+            /* Add a header line to alternate pages, if required */
+            if (add_page_headers  &&  (sends & 2))
+                t4_tx_set_header_info(&send_state, "Header");
+            else
+                t4_tx_set_header_info(&send_state, NULL);
+            if (restart_pages  &&  (sends & 1))
+            {
+                /* Use restart, to send the page a second time */
+                if (t4_tx_restart_page(&send_state))
+                    break;
+            }
+            else
+            {
+                if (compression_step >= 0)
+                {
+                    compression = compression_sequence[compression_step++];
+                    if (compression_step > 2)
+                        compression_step = 0;
+                }
+                t4_tx_set_tx_encoding(&send_state, compression);
+                t4_rx_set_rx_encoding(&receive_state, compression);
+
+                if (t4_tx_start_page(&send_state))
+                    break;
+            }
+            t4_rx_start_page(&receive_state);
+            detect_page_end(-1000000, compression);
+            page_ended = FALSE;
+            if (block_size == 0)
+            {
+                for (;;)
+                {
+                    bit = t4_tx_get_bit(&send_state);
+                    /* Monitor whether the EOLs are there in the correct amount */
+                    if ((res = detect_page_end(bit, page_ended)))
+                    {
+                        tests_failed += (res - 1);
+                        break;
+                    }
+                    if (!page_ended)
+                    {
+                        if (bit_error_rate)
+                        {
+                            if ((rand() % bit_error_rate) == 0)
+                                bit ^= 1;
+                        }
+                        if (t4_rx_put_bit(&receive_state, bit & 1))
+                            page_ended = TRUE;
+                    }
+                }
+                /* Now throw junk at the receive context, to ensure stuff occuring
+                   after the end of page condition has no bad effect. */
+                for (i = 0;  i < 1000;  i++)
+                {
+                    t4_rx_put_bit(&receive_state, (rand() >> 10) & 1);
+                }
+            }
+            else if (block_size == 1)
+            {
+                do
+                {
+                    bit = t4_tx_get_byte(&send_state);
+                    if ((bit & 0x100))
+                    {
+                        if (++end_marks > 50)
+                        {
+                            printf("Receiver missed the end of page mark\n");
+                            tests_failed++;
+                            break;
+                        }
+                    }
+                    end_of_page = t4_rx_put_byte(&receive_state, bit & 0xFF);
+                }
+                while (!end_of_page);
+            }
+            else
+            {
+                do
+                {
+                    bit = t4_tx_get_chunk(&send_state, block, block_size);
+                    if (bit > 0)
+                        end_of_page = t4_rx_put_chunk(&receive_state, block, bit);
+                    if (bit < block_size)
+                    {
+                        if (++end_marks > 50)
+                        {
+                            printf("Receiver missed the end of page mark\n");
+                            tests_failed++;
+                            break;
+                        }
+                    }
+                }
+                while (!end_of_page);
+            }
+            if (dump_as_xxx)
+                dump_image_as_xxx(&receive_state);
+            display_page_stats(&receive_state);
+            if (!restart_pages  ||  (sends & 1))
+                t4_tx_end_page(&send_state);
+            t4_rx_end_page(&receive_state);
+            sends++;
+        }
+        t4_tx_release(&send_state);
+        t4_rx_release(&receive_state);
+        /* And we should now have a matching received TIFF file. Note this will only match
+           at the image level. TIFF files allow a lot of ways to express the same thing,
+           so bit matching of the files is not the normal case. */
+        fflush(stdout);
+        sprintf(buf, "tiffcmp -t %s %s", in_file_name, OUT_FILE_NAME);
+        if (tests_failed  ||  system(buf))
+        {
+            printf("Tests failed\n");
+            exit(2);
+        }
+#endif
+        printf("Tests passed\n");
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.