t4_tests.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * t4_tests.c - ITU T.4 FAX image to and from TIFF file tests
  5. *
  6. * Written by Steve Underwood <steveu@coppice.org>
  7. *
  8. * Copyright (C) 2003 Steve Underwood
  9. *
  10. * All rights reserved.
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License version 2, as
  14. * published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24. */
  25. /*! \file */
  26. /*! \page t4_tests_page T.4 tests
  27. \section t4_tests_page_sec_1 What does it do
  28. These tests exercise the image compression and decompression methods defined
  29. in ITU specifications T.4 and T.6.
  30. */
  31. #if defined(HAVE_CONFIG_H)
  32. #include "config.h"
  33. #endif
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <fcntl.h>
  37. #include <unistd.h>
  38. #include <memory.h>
  39. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  40. #include "spandsp.h"
  41. #define IN_FILE_NAME "../test-data/itu/fax/itutests.tif"
  42. #define OUT_FILE_NAME "t4_tests_receive.tif"
  43. #define XSIZE 1728
  44. t4_tx_state_t *send_state;
  45. t4_rx_state_t *receive_state;
  46. int rows_written = 0;
  47. int rows_read = 0;
  48. static void dump_image_as_xxx(t4_rx_state_t *state)
  49. {
  50. #if 0
  51. uint8_t *s;
  52. int i;
  53. int j;
  54. int k;
  55. /* Dump the entire image as text 'X's and spaces */
  56. printf("Image (%d x %d):\n", state->t4_t6.image_width, state->t4_t6.image_length);
  57. s = state->image_buffer;
  58. for (i = 0; i < state->t4_t6.image_length; i++)
  59. {
  60. for (j = 0; j < state->t4_t6.bytes_per_row; j++)
  61. {
  62. for (k = 0; k < 8; k++)
  63. printf((state->image_buffer[i*state->t4_t6.bytes_per_row + j] & (0x80 >> k)) ? "X" : " ");
  64. }
  65. printf("\n");
  66. }
  67. #endif
  68. }
  69. /*- End of function --------------------------------------------------------*/
  70. static void display_page_stats(t4_rx_state_t *s)
  71. {
  72. t4_stats_t stats;
  73. t4_rx_get_transfer_statistics(s, &stats);
  74. printf("Pages = %d\n", stats.pages_transferred);
  75. printf("Compression = %s\n", t4_compression_to_str(stats.compression));
  76. printf("Compressed size = %d\n", stats.line_image_size);
  77. printf("Raw image size = %d pels x %d pels\n", stats.image_width, stats.image_length);
  78. printf("Image size = %d pels x %d pels\n", stats.width, stats.length);
  79. printf("Raw image resolution = %d pels/m x %d pels/m\n", stats.image_x_resolution, stats.image_y_resolution);
  80. printf("Image resolution = %d pels/m x %d pels/m\n", stats.x_resolution, stats.y_resolution);
  81. printf("Bad rows = %d\n", stats.bad_rows);
  82. printf("Longest bad row run = %d\n", stats.longest_bad_row_run);
  83. printf("Bits per row - min %d, max %d\n", s->decoder.t4_t6.min_row_bits, s->decoder.t4_t6.max_row_bits);
  84. }
  85. /*- End of function --------------------------------------------------------*/
  86. static int detect_non_ecm_page_end(int bit, int page_ended)
  87. {
  88. static int consecutive_eols;
  89. static int max_consecutive_eols;
  90. static int consecutive_zeros;
  91. static int consecutive_ones;
  92. static int eol_zeros;
  93. static int eol_ones;
  94. static int expected_eols;
  95. static int end_marks;
  96. /* Check the EOLs are added properly to the end of a non-ECM image. We can't rely
  97. on the decoder giving the right answer, as a full set of EOLs is not needed for
  98. the decoder to work. */
  99. if (bit == -1)
  100. {
  101. /* Reset */
  102. consecutive_eols = 0;
  103. max_consecutive_eols = 0;
  104. consecutive_zeros = 0;
  105. consecutive_ones = 0;
  106. end_marks = 0;
  107. eol_zeros = 11;
  108. eol_ones = (page_ended == T4_COMPRESSION_T4_2D) ? 2 : 1;
  109. expected_eols = (page_ended == T4_COMPRESSION_T6) ? 2 : 6;
  110. return 0;
  111. }
  112. /* Monitor whether the EOLs are there in the correct amount */
  113. if (bit == 0)
  114. {
  115. consecutive_zeros++;
  116. consecutive_ones = 0;
  117. }
  118. else if (bit == 1)
  119. {
  120. if (++consecutive_ones == eol_ones)
  121. {
  122. if (consecutive_eols == 0 && consecutive_zeros >= eol_zeros)
  123. consecutive_eols++;
  124. else if (consecutive_zeros == eol_zeros)
  125. consecutive_eols++;
  126. else
  127. consecutive_eols = 0;
  128. consecutive_zeros = 0;
  129. consecutive_ones = 0;
  130. }
  131. if (max_consecutive_eols < consecutive_eols)
  132. max_consecutive_eols = consecutive_eols;
  133. }
  134. else if (bit == SIG_STATUS_END_OF_DATA)
  135. {
  136. if (end_marks == 0)
  137. {
  138. if (max_consecutive_eols != expected_eols)
  139. {
  140. printf("Only %d EOLs (should be %d)\n", max_consecutive_eols, expected_eols);
  141. return 2;
  142. }
  143. consecutive_zeros = 0;
  144. consecutive_eols = 0;
  145. max_consecutive_eols = 0;
  146. }
  147. if (!page_ended)
  148. {
  149. /* We might need to push a few bits to get the receiver to report the
  150. end of page condition (at least with T.6). */
  151. if (++end_marks > 50)
  152. {
  153. printf("Receiver missed the end of page mark\n");
  154. return 2;
  155. }
  156. return 0;
  157. }
  158. return 1;
  159. }
  160. return 0;
  161. }
  162. /*- End of function --------------------------------------------------------*/
  163. int main(int argc, char *argv[])
  164. {
  165. static const int compression_sequence[] =
  166. {
  167. //T4_COMPRESSION_NONE,
  168. T4_COMPRESSION_T4_1D,
  169. T4_COMPRESSION_T4_2D,
  170. T4_COMPRESSION_T6,
  171. T4_COMPRESSION_T85,
  172. T4_COMPRESSION_T85_L0,
  173. #if defined(SPANDSP_SUPPORT_T88x)
  174. T4_COMPRESSION_T88,
  175. #endif
  176. #if defined(SPANDSP_SUPPORT_T42x)
  177. T4_COMPRESSION_T42_T81,
  178. T4_COMPRESSION_SYCC_T81,
  179. #endif
  180. #if defined(SPANDSP_SUPPORT_T43x)
  181. T4_COMPRESSION_T43,
  182. #endif
  183. #if defined(SPANDSP_SUPPORT_T45x)
  184. T4_COMPRESSION_T45,
  185. #endif
  186. -1
  187. };
  188. int sends;
  189. int bit;
  190. int end_of_page;
  191. int end_marks;
  192. int res;
  193. int compression;
  194. int compression_step;
  195. int min_row_bits;
  196. int block_size;
  197. char buf[1024];
  198. uint8_t block[1024];
  199. const char *in_file_name;
  200. const char *decode_file_name;
  201. const char *page_header_tz;
  202. tz_t tz;
  203. int opt;
  204. int len;
  205. int i;
  206. int bit_error_rate;
  207. int tests_failed;
  208. bool restart_pages;
  209. bool add_page_headers;
  210. bool overlay_page_headers;
  211. bool dump_as_xxx;
  212. unsigned int last_pkt_no;
  213. unsigned int pkt_no;
  214. int page_ended;
  215. FILE *file;
  216. tests_failed = 0;
  217. compression = -1;
  218. compression_step = 0;
  219. add_page_headers = false;
  220. overlay_page_headers = false;
  221. restart_pages = false;
  222. in_file_name = IN_FILE_NAME;
  223. decode_file_name = NULL;
  224. page_header_tz = NULL;
  225. /* Use a non-zero default minimum row length to ensure we test the consecutive EOLs part
  226. properly. */
  227. min_row_bits = 50;
  228. block_size = 1;
  229. bit_error_rate = 0;
  230. dump_as_xxx = false;
  231. while ((opt = getopt(argc, argv, "b:c:d:ehHri:m:t:x")) != -1)
  232. {
  233. switch (opt)
  234. {
  235. case 'b':
  236. block_size = atoi(optarg);
  237. if (block_size > 1024)
  238. {
  239. printf("Block size too large. Must be 1024 or less\n");
  240. exit(2);
  241. }
  242. break;
  243. case 'c':
  244. if (strcmp(optarg, "T41D") == 0)
  245. {
  246. compression = T4_COMPRESSION_T4_1D;
  247. compression_step = -1;
  248. }
  249. else if (strcmp(optarg, "T42D") == 0)
  250. {
  251. compression = T4_COMPRESSION_T4_2D;
  252. compression_step = -1;
  253. }
  254. else if (strcmp(optarg, "T6") == 0)
  255. {
  256. compression = T4_COMPRESSION_T6;
  257. compression_step = -1;
  258. }
  259. else if (strcmp(optarg, "T85") == 0)
  260. {
  261. compression = T4_COMPRESSION_T85;
  262. compression_step = -1;
  263. }
  264. #if defined(SPANDSP_SUPPORT_T88)
  265. else if (strcmp(optarg, "T88") == 0)
  266. {
  267. compression = T4_COMPRESSION_T88;
  268. compression_step = -1;
  269. }
  270. #endif
  271. else if (strcmp(optarg, "T81") == 0)
  272. {
  273. compression = T4_COMPRESSION_T42_T81;
  274. compression_step = -1;
  275. }
  276. else if (strcmp(optarg, "T43") == 0)
  277. {
  278. compression = T4_COMPRESSION_T43;
  279. compression_step = -1;
  280. }
  281. #if defined(SPANDSP_SUPPORT_T45)
  282. else if (strcmp(optarg, "T45") == 0)
  283. {
  284. compression = T4_COMPRESSION_T45;
  285. compression_step = -1;
  286. }
  287. #endif
  288. else
  289. {
  290. printf("Unrecognised compression.\n");
  291. exit(2);
  292. }
  293. break;
  294. case 'd':
  295. decode_file_name = optarg;
  296. break;
  297. case 'e':
  298. bit_error_rate = 0x3FF;
  299. break;
  300. case 'h':
  301. add_page_headers = true;
  302. overlay_page_headers = false;
  303. break;
  304. case 'H':
  305. add_page_headers = true;
  306. overlay_page_headers = true;
  307. break;
  308. case 'r':
  309. restart_pages = true;
  310. break;
  311. case 'i':
  312. in_file_name = optarg;
  313. break;
  314. case 'm':
  315. min_row_bits = atoi(optarg);
  316. break;
  317. case 't':
  318. page_header_tz = optarg;
  319. break;
  320. case 'x':
  321. dump_as_xxx = true;
  322. break;
  323. default:
  324. //usage();
  325. exit(2);
  326. break;
  327. }
  328. }
  329. end_of_page = T4_DECODE_MORE_DATA;
  330. if (decode_file_name)
  331. {
  332. if (compression < 0)
  333. compression = T4_COMPRESSION_T4_1D;
  334. /* Receive end puts TIFF to a new file. We assume the receive width here. */
  335. if ((receive_state = t4_rx_init(NULL, OUT_FILE_NAME, T4_COMPRESSION_T4_2D)) == NULL)
  336. {
  337. printf("Failed to init T.4 rx\n");
  338. exit(2);
  339. }
  340. span_log_set_level(t4_rx_get_logging_state(receive_state), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
  341. t4_rx_set_rx_encoding(receive_state, compression);
  342. t4_rx_set_x_resolution(receive_state, T4_X_RESOLUTION_R8);
  343. //t4_rx_set_y_resolution(receive_state, T4_Y_RESOLUTION_FINE);
  344. t4_rx_set_y_resolution(receive_state, T4_Y_RESOLUTION_STANDARD);
  345. t4_rx_set_image_width(receive_state, XSIZE);
  346. t4_rx_start_page(receive_state);
  347. last_pkt_no = 0;
  348. file = fopen(decode_file_name, "r");
  349. while (fgets(buf, 1024, file))
  350. {
  351. if (sscanf(buf, "HDLC: FCD: 06 %x", &pkt_no) == 1)
  352. {
  353. /* Useful for breaking up T.38 ECM logs */
  354. for (i = 0; i < 256; i++)
  355. {
  356. if (sscanf(&buf[18 + 3*i], "%x", (unsigned int *) &bit) != 1)
  357. break;
  358. block[i] = bit;
  359. }
  360. end_of_page = t4_rx_put(receive_state, block, i);
  361. }
  362. else if (sscanf(buf, "HDLC: %x", &pkt_no) == 1)
  363. {
  364. /* Useful for breaking up HDLC decodes of ECM logs */
  365. for (i = 0; i < 256; i++)
  366. {
  367. if (sscanf(&buf[19 + 3*i], "%x", (unsigned int *) &bit) != 1)
  368. break;
  369. block[i] = bit;
  370. }
  371. end_of_page = t4_rx_put(receive_state, block, i);
  372. }
  373. else if (sscanf(buf, "%*d:%*d:%*d.%*d T.38 Rx %d: IFP %x %x", &pkt_no, (unsigned int *) &bit, (unsigned int *) &bit) == 3)
  374. {
  375. /* Useful for breaking up T.38 non-ECM logs */
  376. if (pkt_no != last_pkt_no + 1)
  377. printf("Packet %u\n", pkt_no);
  378. last_pkt_no = pkt_no;
  379. for (i = 0; i < 256; i++)
  380. {
  381. if (sscanf(&buf[47 + 3*i], "%x", (unsigned int *) &bit) != 1)
  382. break;
  383. block[i] = bit_reverse8(bit);
  384. }
  385. end_of_page = t4_rx_put(receive_state, block, i);
  386. }
  387. else if (strlen(buf) > 2 && sscanf(buf, "T.30 Rx: %x %x %x %x", (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &pkt_no) == 4)
  388. {
  389. /* Useful for breaking up ECM logs */
  390. if (pkt_no != last_pkt_no + 1)
  391. printf("Packet %u\n", pkt_no);
  392. last_pkt_no = pkt_no;
  393. for (i = 0; i < 256; i++)
  394. {
  395. if (sscanf(&buf[22 + 3*i], "%x", (unsigned int *) &bit) != 1)
  396. break;
  397. block[i] = bit_reverse8(bit);
  398. }
  399. end_of_page = t4_rx_put(receive_state, block, i);
  400. }
  401. else if (sscanf(buf, "%04x %02x %02x %02x", (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &bit) == 4)
  402. {
  403. for (i = 0; i < 16; i++)
  404. {
  405. if (sscanf(&buf[6 + 3*i], "%x", (unsigned int *) &bit) != 1)
  406. break;
  407. block[i] = bit_reverse8(bit);
  408. }
  409. end_of_page = t4_rx_put(receive_state, block, i);
  410. }
  411. else if (sscanf(buf, "%08x %02x %02x %02x", (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &bit, (unsigned int *) &bit) == 4)
  412. {
  413. for (i = 0; i < 16; i++)
  414. {
  415. if (sscanf(&buf[10 + 3*i], "%x", (unsigned int *) &bit) != 1)
  416. break;
  417. block[i] = bit_reverse8(bit);
  418. }
  419. end_of_page = t4_rx_put(receive_state, block, i);
  420. }
  421. else if (sscanf(buf, "Rx bit %*d - %d", &bit) == 1)
  422. {
  423. if ((end_of_page = t4_rx_put_bit(receive_state, bit)))
  424. {
  425. printf("End of page detected\n");
  426. break;
  427. }
  428. }
  429. }
  430. fclose(file);
  431. if (dump_as_xxx)
  432. dump_image_as_xxx(receive_state);
  433. t4_rx_end_page(receive_state);
  434. display_page_stats(receive_state);
  435. t4_rx_free(receive_state);
  436. }
  437. else
  438. {
  439. #if 1
  440. printf("Testing TIFF->compress->decompress->TIFF cycle\n");
  441. /* Send end gets TIFF from a file */
  442. if ((send_state = t4_tx_init(NULL, in_file_name, -1, -1)) == NULL)
  443. {
  444. printf("Failed to init T.4 send\n");
  445. exit(2);
  446. }
  447. span_log_set_level(t4_tx_get_logging_state(send_state), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
  448. t4_tx_set_min_bits_per_row(send_state, min_row_bits);
  449. t4_tx_set_local_ident(send_state, "111 2222 3333");
  450. /* Receive end puts TIFF to a new file. */
  451. if ((receive_state = t4_rx_init(NULL, OUT_FILE_NAME, T4_COMPRESSION_T4_2D)) == NULL)
  452. {
  453. printf("Failed to init T.4 rx for '%s'\n", OUT_FILE_NAME);
  454. exit(2);
  455. }
  456. span_log_set_level(t4_rx_get_logging_state(receive_state), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
  457. /* Now send and receive all the pages in the source TIFF file */
  458. sends = 0;
  459. /* If we are stepping around the compression schemes, reset to the start of the sequence. */
  460. if (compression_step > 0)
  461. compression_step = 0;
  462. for (;;)
  463. {
  464. end_marks = 0;
  465. /* Add a header line to alternate pages, if required */
  466. if (add_page_headers && (sends & 2))
  467. t4_tx_set_header_info(send_state, "Header");
  468. else
  469. t4_tx_set_header_info(send_state, NULL);
  470. if (page_header_tz && page_header_tz[0])
  471. {
  472. if (tz_init(&tz, page_header_tz))
  473. t4_tx_set_header_tz(send_state, &tz);
  474. }
  475. t4_tx_set_header_overlays_image(send_state, overlay_page_headers);
  476. if (restart_pages && (sends & 1))
  477. {
  478. /* Use restart, to send the page a second time */
  479. if (t4_tx_restart_page(send_state))
  480. break;
  481. }
  482. else
  483. {
  484. if (compression_step >= 0)
  485. {
  486. compression = compression_sequence[compression_step++];
  487. if (compression < 0 || (block_size == 0 && compression_step >= 3))
  488. {
  489. compression_step = 0;
  490. compression = compression_sequence[compression_step++];
  491. }
  492. }
  493. if (t4_tx_set_tx_image_format(send_state,
  494. compression,
  495. T4_SUPPORT_WIDTH_215MM
  496. | T4_SUPPORT_LENGTH_US_LETTER
  497. | T4_SUPPORT_LENGTH_US_LEGAL
  498. | T4_SUPPORT_LENGTH_UNLIMITED,
  499. T4_RESOLUTION_R8_STANDARD
  500. | T4_RESOLUTION_R8_FINE
  501. | T4_RESOLUTION_R8_SUPERFINE
  502. | T4_RESOLUTION_R16_SUPERFINE
  503. | T4_RESOLUTION_200_100
  504. | T4_RESOLUTION_200_200
  505. | T4_RESOLUTION_200_400
  506. | T4_RESOLUTION_300_300
  507. | T4_RESOLUTION_300_600
  508. | T4_RESOLUTION_400_400
  509. | T4_RESOLUTION_400_800
  510. | T4_RESOLUTION_600_600
  511. | T4_RESOLUTION_600_1200
  512. | T4_RESOLUTION_1200_1200,
  513. T4_RESOLUTION_100_100
  514. | T4_RESOLUTION_200_200
  515. | T4_RESOLUTION_300_300
  516. | T4_RESOLUTION_400_400
  517. | T4_RESOLUTION_600_600
  518. | T4_RESOLUTION_1200_1200) < 0)
  519. {
  520. break;
  521. }
  522. t4_rx_set_rx_encoding(receive_state, compression);
  523. if (t4_tx_start_page(send_state))
  524. break;
  525. t4_rx_set_x_resolution(receive_state, t4_tx_get_tx_x_resolution(send_state));
  526. t4_rx_set_y_resolution(receive_state, t4_tx_get_tx_y_resolution(send_state));
  527. t4_rx_set_image_width(receive_state, t4_tx_get_tx_image_width(send_state));
  528. }
  529. t4_rx_start_page(receive_state);
  530. detect_non_ecm_page_end(-1, compression);
  531. page_ended = false;
  532. switch (block_size)
  533. {
  534. case 0:
  535. /* Bit by bit operation. This is only appropriate for T.4 1D and 2D,
  536. which are used without ECM. */
  537. while ((bit = t4_tx_get_bit(send_state)) >= 0)
  538. {
  539. /* Monitor whether the EOLs are there in the correct amount */
  540. if ((res = detect_non_ecm_page_end(bit, page_ended)))
  541. {
  542. printf("Incorrect EOLs - %d\n", res);
  543. tests_failed += (res - 1);
  544. break;
  545. }
  546. if (bit_error_rate)
  547. {
  548. if ((rand() % bit_error_rate) == 0)
  549. bit ^= 1;
  550. }
  551. end_of_page = t4_rx_put_bit(receive_state, bit);
  552. }
  553. while (end_of_page != T4_DECODE_OK)
  554. {
  555. end_of_page = t4_rx_put_bit(receive_state, 0);
  556. if (++end_marks > 50)
  557. {
  558. printf("Receiver missed the end of page mark\n");
  559. tests_failed++;
  560. break;
  561. }
  562. }
  563. /* Now throw junk at the receive context, to ensure stuff occuring
  564. after the end of page condition has no bad effect. */
  565. for (i = 0; i < 1000; i++)
  566. t4_rx_put_bit(receive_state, (rand() >> 10) & 1);
  567. break;
  568. default:
  569. do
  570. {
  571. len = t4_tx_get(send_state, block, block_size);
  572. if (len > 0)
  573. end_of_page = t4_rx_put(receive_state, block, len);
  574. }
  575. while (len > 0);
  576. /* Some decoders require a few extra bits before they recognise the end
  577. of an image, so be prepared to offer it a few. */
  578. while (end_of_page != T4_DECODE_OK)
  579. {
  580. block[0] = 0;
  581. end_of_page = t4_rx_put(receive_state, block, 1);
  582. if (++end_marks > 5)
  583. {
  584. printf("Receiver missed the end of page mark\n");
  585. tests_failed++;
  586. break;
  587. }
  588. }
  589. break;
  590. }
  591. if (dump_as_xxx)
  592. dump_image_as_xxx(receive_state);
  593. display_page_stats(receive_state);
  594. if (!restart_pages || (sends & 1))
  595. t4_tx_end_page(send_state);
  596. t4_rx_end_page(receive_state);
  597. sends++;
  598. }
  599. t4_tx_free(send_state);
  600. t4_rx_free(receive_state);
  601. /* And we should now have a matching received TIFF file. Note this will only match
  602. at the image level. TIFF files allow a lot of ways to express the same thing,
  603. so bit matching of the files is not the normal case. */
  604. fflush(stdout);
  605. sprintf(buf, "tiffcmp -t %s %s", in_file_name, OUT_FILE_NAME);
  606. if (tests_failed || system(buf))
  607. {
  608. printf("Tests failed\n");
  609. exit(2);
  610. }
  611. #endif
  612. printf("Tests passed\n");
  613. }
  614. return 0;
  615. }
  616. /*- End of function --------------------------------------------------------*/
  617. /*- End of file ------------------------------------------------------------*/