2
0

t85_tests.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * t85_tests.c - ITU T.85 FAX image compression and decompression tests
  5. *
  6. * Written by Steve Underwood <steveu@coppice.org>
  7. *
  8. * Copyright (C) 2009 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. /*
  26. * These tests are based on code from Markus Kuhn's jbigkit. See
  27. * http://www.cl.cam.ac.uk/~mgk25/
  28. *
  29. * jbigkit is GPL2 licenced. This file is also GPL2 licenced, and our
  30. * T.85 code is LGPL2.1 licenced. There are no licence incompatibilities
  31. * in this reuse of Markus's work.
  32. */
  33. /*! \file */
  34. /*! \page t85_tests_page T.85 image compress and decompression tests
  35. \section t85_tests_page_sec_1 What does it do
  36. These tests exercise the image compression and decompression methods defined
  37. in ITU specifications T.85.
  38. */
  39. #if defined(HAVE_CONFIG_H)
  40. #include "config.h"
  41. #endif
  42. #include <inttypes.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <stddef.h>
  46. #include <string.h>
  47. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  48. #include "spandsp.h"
  49. #define TESTBUF_SIZE 400000
  50. #define TEST_IMAGE_SIZE (1951*1960/8)
  51. uint8_t testbuf[TESTBUF_SIZE];
  52. uint8_t test_image[TEST_IMAGE_SIZE];
  53. size_t testbuf_len;
  54. int read_row = 0;
  55. int write_row = 0;
  56. int clip_to_row = 0;
  57. static int row_read_handler(void *user_data, uint8_t buf[], size_t len)
  58. {
  59. memcpy(buf, &test_image[len*read_row], len);
  60. if (clip_to_row && read_row == clip_to_row)
  61. {
  62. clip_to_row = 0;
  63. return 0;
  64. }
  65. read_row++;
  66. return len;
  67. }
  68. /*- End of function --------------------------------------------------------*/
  69. static int row_write_handler(void *user_data, const uint8_t buf[], size_t len)
  70. {
  71. uint8_t *bitmap;
  72. bitmap = (uint8_t *) user_data;
  73. memcpy(&bitmap[len*write_row], buf, len);
  74. //printf("Write row %d\n", write_row);
  75. write_row++;
  76. return 0;
  77. }
  78. /*- End of function --------------------------------------------------------*/
  79. static int comment_handler(void *user_data, const uint8_t buf[], size_t len)
  80. {
  81. if (buf)
  82. printf("Comment (%lu): %s\n", (unsigned long int) len, buf);
  83. else
  84. printf("Comment (%lu): ---\n", (unsigned long int) len);
  85. return 0;
  86. }
  87. /*- End of function --------------------------------------------------------*/
  88. static void create_test_image(uint8_t *pic)
  89. {
  90. int i;
  91. int j;
  92. uint32_t sum;
  93. uint32_t prsg;
  94. uint32_t repeat[8];
  95. uint8_t *p;
  96. /* Cook up the test image defined in T.82/7.2.1. This image is 1960 x 1951
  97. pixels, and occupies a single plane (which it has to for T.85). */
  98. memset(pic, 0, TEST_IMAGE_SIZE);
  99. p = pic;
  100. prsg = 1;
  101. for (i = 0; i < 1951; i++)
  102. {
  103. for (j = 0; j < 1960; j++)
  104. {
  105. if (i >= 192)
  106. {
  107. if (i < 1023 || (j & (3 << 3)) == 0)
  108. {
  109. sum = (prsg & 1)
  110. + ((prsg >> 2) & 1)
  111. + ((prsg >> 11) & 1)
  112. + ((prsg >> 15) & 1);
  113. prsg = (prsg << 1) + (sum & 1);
  114. if ((prsg & 3) == 0)
  115. {
  116. *p |= (1 << (7 - (j & 7)));
  117. repeat[j & 7] = 1;
  118. }
  119. else
  120. {
  121. repeat[j & 7] = 0;
  122. }
  123. }
  124. else
  125. {
  126. if (repeat[j & 7])
  127. *p |= 1 << (7 - (j & 7));
  128. }
  129. }
  130. if ((j & 7) == 7)
  131. ++p;
  132. }
  133. }
  134. /* Verify the test image has been generated OK, by checking the number of set pixels */
  135. sum = 0;
  136. for (i = 0; i < TEST_IMAGE_SIZE; i++)
  137. {
  138. for (j = 0; j < 8; j++)
  139. sum += ((pic[i] >> j) & 1);
  140. }
  141. if (sum != 861965)
  142. {
  143. printf("WARNING: Test image has %" PRIu32 " foreground pixels. There should be 861965.\n",
  144. sum);
  145. }
  146. }
  147. /*- End of function --------------------------------------------------------*/
  148. /* Perform a test cycle, as defined in T.82/7, with one set of parameters. */
  149. static int test_cycle(const char *test_id,
  150. const uint8_t *image,
  151. uint32_t width,
  152. uint32_t height,
  153. uint32_t l0,
  154. int mx,
  155. int options,
  156. int optionsx,
  157. const uint8_t *comment,
  158. size_t correct_length)
  159. {
  160. t85_encode_state_t *t85_enc;
  161. t85_decode_state_t *t85_dec;
  162. long int l;
  163. size_t image_size;
  164. int result;
  165. int len;
  166. int max_len;
  167. size_t bytes_per_row;
  168. size_t cnt_a;
  169. size_t cnt_b;
  170. uint8_t *decoded_image;
  171. printf("%s: TPBON=%d, LRLTWO=%d, Mx=%d, L0=%" PRIu32 "\n",
  172. test_id,
  173. (options & T85_TPBON) ? 1 : 0,
  174. (options & T85_LRLTWO) ? 1 : 0,
  175. mx,
  176. l0);
  177. printf("%s.1: Encode\n", test_id);
  178. bytes_per_row = (width + 7)/8;
  179. image_size = bytes_per_row*height;
  180. if ((optionsx & T85_VLENGTH))
  181. {
  182. t85_enc = t85_encode_init(NULL, width, height + 10, row_read_handler, NULL);
  183. clip_to_row = height;
  184. }
  185. else
  186. {
  187. t85_enc = t85_encode_init(NULL, width, height, row_read_handler, NULL);
  188. clip_to_row = 0;
  189. }
  190. read_row = 0;
  191. t85_encode_set_options(t85_enc, l0, mx, options);
  192. /* A comment inserted here should always succeed. The later one, inserted some way
  193. down the image, will only succeed if a new chunk is started afterwards. */
  194. if (comment)
  195. t85_encode_comment(t85_enc, comment, strlen((const char *) comment) + 1);
  196. testbuf_len = 0;
  197. max_len = 100;
  198. while ((len = t85_encode_get(t85_enc, &testbuf[testbuf_len], max_len)) > 0)
  199. {
  200. testbuf_len += len;
  201. max_len = 100;
  202. if (testbuf_len + 100 > TESTBUF_SIZE)
  203. max_len = TESTBUF_SIZE - testbuf_len;
  204. if (comment && testbuf_len == 1000)
  205. t85_encode_comment(t85_enc, comment, strlen((const char *) comment) + 1);
  206. }
  207. printf("Encoded BIE has %lu bytes\n", (unsigned long int) testbuf_len);
  208. if (correct_length > 0)
  209. {
  210. if (testbuf_len != correct_length)
  211. {
  212. printf("Incorrect encoded length. Should have been %lu\n", (unsigned long int) correct_length);
  213. printf("Test failed\n");
  214. exit(2);
  215. }
  216. printf("Test passed\n");
  217. }
  218. cnt_a = t85_encode_get_compressed_image_size(t85_enc);
  219. t85_encode_free(t85_enc);
  220. printf("%s.2: Decode in one big chunk\n", test_id);
  221. if ((decoded_image = (uint8_t *) malloc(image_size)) == NULL)
  222. {
  223. fprintf(stderr, "Out of memory!\n");
  224. exit(2);
  225. }
  226. t85_dec = t85_decode_init(NULL, row_write_handler, decoded_image);
  227. if (comment && comment[0] != 'X')
  228. t85_decode_set_comment_handler(t85_dec, 1000, comment_handler, NULL);
  229. write_row = 0;
  230. result = t85_decode_put(t85_dec, testbuf, testbuf_len);
  231. if (result == T4_DECODE_MORE_DATA)
  232. result = t85_decode_put(t85_dec, NULL, 0);
  233. cnt_b = t85_decode_get_compressed_image_size(t85_dec);
  234. if (cnt_a != cnt_b || cnt_a != testbuf_len*8 || result != T4_DECODE_OK)
  235. {
  236. printf("Decode result %d\n", result);
  237. printf("%ld/%ld bits of %ld bits of BIE read. %lu lines decoded.\n",
  238. (long int) cnt_a,
  239. (long int) cnt_b,
  240. (unsigned long int) testbuf_len*8,
  241. (unsigned long int) t85_dec->y);
  242. printf("Test failed\n");
  243. exit(2);
  244. }
  245. if (memcmp(decoded_image, image, image_size))
  246. {
  247. printf("Image mismatch\n");
  248. printf("Test failed\n");
  249. exit(2);
  250. }
  251. free(decoded_image);
  252. t85_decode_free(t85_dec);
  253. printf("Test passed\n");
  254. printf("%s.3: Decode byte by byte\n", test_id);
  255. if ((decoded_image = (uint8_t *) malloc(image_size)) == NULL)
  256. {
  257. fprintf(stderr, "Out of memory!\n");
  258. exit(2);
  259. }
  260. t85_dec = t85_decode_init(NULL, row_write_handler, decoded_image);
  261. if (comment && comment[0] != 'X')
  262. t85_decode_set_comment_handler(t85_dec, 1000, comment_handler, NULL);
  263. write_row = 0;
  264. result = T4_DECODE_MORE_DATA;
  265. for (l = 0; l < testbuf_len; l++)
  266. {
  267. result = t85_decode_put(t85_dec, &testbuf[l], 1);
  268. if (result != T4_DECODE_MORE_DATA)
  269. {
  270. l++;
  271. break;
  272. }
  273. }
  274. if (result == T4_DECODE_MORE_DATA)
  275. result = t85_decode_put(t85_dec, NULL, 0);
  276. if (l != testbuf_len || result != T4_DECODE_OK)
  277. {
  278. printf("Decode result %d\n", result);
  279. printf("%ld bytes of %ld bytes of BIE read. %lu lines decoded.\n",
  280. (long int) l,
  281. (unsigned long int) testbuf_len,
  282. (unsigned long int) t85_dec->y);
  283. printf("Test failed\n");
  284. exit(2);
  285. }
  286. if (memcmp(decoded_image, image, image_size))
  287. {
  288. printf("Image mismatch\n");
  289. printf("Test failed\n");
  290. exit(2);
  291. }
  292. free(decoded_image);
  293. t85_decode_free(t85_dec);
  294. printf("Test passed\n");
  295. return 0;
  296. }
  297. /*- End of function --------------------------------------------------------*/
  298. int main(int argc, char **argv)
  299. {
  300. printf("T.85 JBIG for FAX encoder and decoder tests, from ITU-T T.82\n\n");
  301. printf("Generating the test image from T.82...\n");
  302. create_test_image(test_image);
  303. /* Run through the tests in T.82/7.2, which are applicable to T.85 */
  304. test_cycle("1", test_image, 1960, 1951, 1951, 0, 0, 0, NULL, 317384);
  305. test_cycle("2", test_image, 1960, 1951, 1951, 0, T85_LRLTWO, 0, NULL, 317132);
  306. test_cycle("3", test_image, 1960, 1951, 128, 8, T85_TPBON, 0, NULL, 253653);
  307. /* Again with a comment added and handled */
  308. test_cycle("4", test_image, 1960, 1951, 1951, 0, 0, 0, (const uint8_t *) "Comment 4", 317384 + 16);
  309. test_cycle("5", test_image, 1960, 1951, 1951, 0, T85_LRLTWO, 0, (const uint8_t *) "Comment 5", 317132 + 16);
  310. test_cycle("6", test_image, 1960, 1951, 128, 8, T85_TPBON, 0, (const uint8_t *) "Comment 6", 253653 + 2*16);
  311. /* Again with a comment added, but not handled */
  312. test_cycle("7", test_image, 1960, 1951, 1951, 0, 0, 0, (const uint8_t *) "Xomment 7", 317384 + 16);
  313. test_cycle("8", test_image, 1960, 1951, 1951, 0, T85_LRLTWO, 0, (const uint8_t *) "Xomment 8", 317132 + 16);
  314. test_cycle("9", test_image, 1960, 1951, 128, 8, T85_TPBON, 0, (const uint8_t *) "Xomment 9", 253653 + 2*16);
  315. /* Again with the image variable length and prematurely terminated */
  316. test_cycle("10", test_image, 1960, 1951, 1951, 0, T85_VLENGTH, T85_VLENGTH, NULL, 317384 + 8);
  317. test_cycle("11", test_image, 1960, 1951, 1951, 0, T85_VLENGTH | T85_LRLTWO, T85_VLENGTH, NULL, 317132 + 8);
  318. test_cycle("12", test_image, 1960, 1951, 128, 8, T85_VLENGTH | T85_TPBON, T85_VLENGTH, NULL, 253653 + 8);
  319. /* Again with the image variable length but not prematurely terminated */
  320. test_cycle("13", test_image, 1960, 1951, 1951, 0, T85_VLENGTH, 0, NULL, 317384);
  321. test_cycle("14", test_image, 1960, 1951, 1951, 0, T85_VLENGTH | T85_LRLTWO, 0, NULL, 317132);
  322. test_cycle("15", test_image, 1960, 1951, 128, 8, T85_VLENGTH | T85_TPBON, 0, NULL, 253653);
  323. printf("Tests passed\n");
  324. return 0;
  325. }
  326. /*- End of function --------------------------------------------------------*/
  327. /*- End of file ------------------------------------------------------------*/