2
0

t42_tests.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * t42_tests.c - ITU T.42 JPEG for FAX image processing
  5. *
  6. * Written by Steve Underwood <steveu@coppice.org>
  7. *
  8. * Copyright (C) 2011 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 t42_tests_page T.42 tests
  27. \section t42_tests_page_sec_1 What does it do
  28. */
  29. #if defined(HAVE_CONFIG_H)
  30. #include "config.h"
  31. #endif
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <fcntl.h>
  35. #include <unistd.h>
  36. #include <memory.h>
  37. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  38. #include "spandsp.h"
  39. #if defined(SPANDSP_SUPPORT_TIFF_FX) && defined(HAVE_TIF_DIR_H)
  40. #include <tif_dir.h>
  41. #endif
  42. #define IN_FILE_NAME "../test-data/itu/t24/F21B400.TIF"
  43. #define OUT_FILE_NAME "t42_tests_receive.tif"
  44. uint8_t data5[50000000];
  45. int data5_ptr = 0;
  46. int plane = 0;
  47. int bit_mask;
  48. uint8_t colour_map[3*256];
  49. lab_params_t lab_param;
  50. int write_row = 0;
  51. static __inline__ uint16_t pack_16(uint8_t *s)
  52. {
  53. uint16_t value;
  54. value = ((uint16_t) s[0] << 8) | (uint16_t) s[1];
  55. return value;
  56. }
  57. /*- End of function --------------------------------------------------------*/
  58. static __inline__ uint32_t pack_32(uint8_t *s)
  59. {
  60. uint32_t value;
  61. value = ((uint32_t) s[0] << 24) | ((uint32_t) s[1] << 16) | ((uint32_t) s[2] << 8) | (uint32_t) s[3];
  62. return value;
  63. }
  64. /*- End of function --------------------------------------------------------*/
  65. static int t85_row_write_handler(void *user_data, const uint8_t buf[], size_t len)
  66. {
  67. int i;
  68. int j;
  69. for (i = 0; i < len; i++)
  70. {
  71. for (j = 0; j < 8; j++)
  72. {
  73. if ((buf[i] & (0x80 >> j)))
  74. data5[data5_ptr + 3*(8*i + j)] |= bit_mask;
  75. else
  76. data5[data5_ptr + 3*(8*i + j)] &= ~bit_mask;
  77. }
  78. }
  79. data5_ptr += 3*8*len;
  80. write_row++;
  81. return 0;
  82. }
  83. /*- End of function --------------------------------------------------------*/
  84. static int t85_comment_handler(void *user_data, const uint8_t buf[], size_t len)
  85. {
  86. if (buf)
  87. printf("Comment (%lu): %s\n", (unsigned long int) len, buf);
  88. else
  89. printf("Comment (%lu): ---\n", (unsigned long int) len);
  90. return 0;
  91. }
  92. /*- End of function --------------------------------------------------------*/
  93. int main(int argc, char *argv[])
  94. {
  95. TIFF *tif;
  96. uint32_t w;
  97. uint32_t h;
  98. tstrip_t nstrips;
  99. uint32_t totdata;
  100. tsize_t off;
  101. uint8_t *data;
  102. uint8_t *data2;
  103. int row;
  104. uint16_t compression;
  105. int16_t photometric;
  106. int16_t YCbCrSubsampleHoriz;
  107. int16_t YCbCrSubsampleVert;
  108. int16_t bits_per_pixel;
  109. int16_t samples_per_pixel;
  110. int16_t planar_config;
  111. int bytes_per_row;
  112. tsize_t outsize;
  113. char *outptr;
  114. const char *source_file;
  115. int i;
  116. int j;
  117. int len;
  118. tsize_t total_image_len;
  119. tsize_t total_len;
  120. int process_raw;
  121. int result;
  122. t85_decode_state_t t85_dec;
  123. uint64_t start;
  124. uint64_t end;
  125. uint16_t *map_L;
  126. uint16_t *map_a;
  127. uint16_t *map_b;
  128. uint16_t *map_z;
  129. uint32_t jpeg_table_len;
  130. #if 0
  131. logging_state_t *logging;
  132. #endif
  133. printf("Demo of ITU/Lab library.\n");
  134. #if 0
  135. logging = span_log_init(NULL, SPAN_LOG_FLOW, "T.42");
  136. #endif
  137. #if defined(SPANDSP_SUPPORT_TIFF_FX) && defined(HAVE_TIF_DIR_H)
  138. TIFF_FX_init();
  139. #endif
  140. /* The default luminant is D50 */
  141. set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f);
  142. set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, false);
  143. source_file = (argc > 1) ? argv[1] : IN_FILE_NAME;
  144. /* sRGB to ITU */
  145. if ((tif = TIFFOpen(source_file, "r")) == NULL)
  146. {
  147. printf("Unable to open '%s'!\n", source_file);
  148. return 1;
  149. }
  150. if (TIFFSetDirectory(tif, (tdir_t) 0) < 0)
  151. {
  152. printf("Unable to set directory '%s'!\n", source_file);
  153. return 1;
  154. }
  155. w = 0;
  156. TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
  157. h = 0;
  158. TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
  159. bits_per_pixel = 0;
  160. TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits_per_pixel);
  161. samples_per_pixel = 0;
  162. TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
  163. compression = 0;
  164. TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
  165. photometric = 0;
  166. TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
  167. YCbCrSubsampleHoriz = 0;
  168. YCbCrSubsampleVert = 0;
  169. TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, &YCbCrSubsampleHoriz, &YCbCrSubsampleVert);
  170. planar_config = PLANARCONFIG_CONTIG;
  171. TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config);
  172. off = 0;
  173. map_L = NULL;
  174. map_a = NULL;
  175. map_b = NULL;
  176. map_z = NULL;
  177. if (TIFFGetField(tif, TIFFTAG_COLORMAP, &map_L, &map_a, &map_b, &map_z))
  178. {
  179. #if 0
  180. /* Sweep the colormap in the proper order */
  181. for (i = 0; i < (1 << bits_per_pixel); i++)
  182. {
  183. colour_map[3*i] = (map_L[i] >> 8) & 0xFF;
  184. colour_map[3*i + 1] = (map_a[i] >> 8) & 0xFF;
  185. colour_map[3*i + 2] = (map_b[i] >> 8) & 0xFF;
  186. printf("Map %3d - %5d %5d %5d\n", i, colour_map[3*i], colour_map[3*i + 1], colour_map[3*i + 2]);
  187. }
  188. #else
  189. /* Sweep the colormap in the order that seems to work for l04x_02x.tif */
  190. for (i = 0; i < (1 << bits_per_pixel); i++)
  191. {
  192. colour_map[i] = (map_L[i] >> 8) & 0xFF;
  193. colour_map[256 + i] = (map_a[i] >> 8) & 0xFF;
  194. colour_map[2*256 + i] = (map_b[i] >> 8) & 0xFF;
  195. }
  196. #endif
  197. lab_params_t lab;
  198. /* The default luminant is D50 */
  199. set_lab_illuminant(&lab, 96.422f, 100.000f, 82.521f);
  200. set_lab_gamut(&lab, 0, 100, -85, 85, -75, 125, false);
  201. lab_to_srgb(&lab, colour_map, colour_map, 256);
  202. for (i = 0; i < (1 << bits_per_pixel); i++)
  203. printf("Map %3d - %5d %5d %5d\n", i, colour_map[3*i], colour_map[3*i + 1], colour_map[3*i + 2]);
  204. }
  205. else
  206. {
  207. printf("There is no colour map\n");
  208. }
  209. process_raw = false;
  210. printf("Compression is ");
  211. switch (compression)
  212. {
  213. case COMPRESSION_CCITT_T4:
  214. printf("T.4\n");
  215. return 0;
  216. case COMPRESSION_CCITT_T6:
  217. printf("T.6\n");
  218. return 0;
  219. case COMPRESSION_T85:
  220. printf("T.85\n");
  221. process_raw = true;
  222. break;
  223. case COMPRESSION_T43:
  224. printf("T.43\n");
  225. process_raw = true;
  226. break;
  227. case COMPRESSION_JPEG:
  228. printf("JPEG");
  229. if (photometric == PHOTOMETRIC_ITULAB)
  230. {
  231. printf(" ITULAB");
  232. process_raw = true;
  233. }
  234. printf("\n");
  235. break;
  236. case COMPRESSION_NONE:
  237. printf("No compression\n");
  238. break;
  239. default:
  240. printf("Unexpected compression %d\n", compression);
  241. break;
  242. }
  243. outsize = 0;
  244. if (process_raw)
  245. {
  246. uint8_t *jpeg_table;
  247. nstrips = TIFFNumberOfStrips(tif);
  248. total_image_len = 0;
  249. jpeg_table_len = 0;
  250. if (TIFFGetField(tif, TIFFTAG_JPEGTABLES, &jpeg_table_len, &jpeg_table))
  251. {
  252. total_image_len += (jpeg_table_len - 4);
  253. printf("JPEG tables %u\n", jpeg_table_len);
  254. printf("YYY %d - %x %x %x %x\n", jpeg_table_len, jpeg_table[0], jpeg_table[1], jpeg_table[2], jpeg_table[3]);
  255. }
  256. for (i = 0, total_image_len = 0; i < nstrips; i++)
  257. total_image_len += TIFFRawStripSize(tif, i);
  258. if ((data = malloc(total_image_len)) == NULL)
  259. {
  260. printf("Failed to allocate buffer\n");
  261. exit(2);
  262. }
  263. for (i = 0, total_len = 0; i < nstrips; i++, total_len += len)
  264. {
  265. if ((len = TIFFReadRawStrip(tif, i, &data[total_len], total_image_len - total_len)) < 0)
  266. {
  267. printf("TIFF read error.\n");
  268. return -1;
  269. }
  270. }
  271. if (jpeg_table_len > 0)
  272. memcpy(data, jpeg_table, jpeg_table_len - 2);
  273. if (total_len != total_image_len)
  274. printf("Size mismatch %ld %ld\n", (long int) total_len, (long int) total_image_len);
  275. off = total_len;
  276. switch (compression)
  277. {
  278. case COMPRESSION_CCITT_T4:
  279. break;
  280. case COMPRESSION_CCITT_T6:
  281. break;
  282. case COMPRESSION_T85:
  283. printf("T.85 image %ld bytes\n", (long int) total_len);
  284. for (i = 0; i < 16; i++)
  285. printf("0x%02x\n", data[i]);
  286. t85_decode_init(&t85_dec, t85_row_write_handler, NULL);
  287. t85_decode_set_comment_handler(&t85_dec, 1000, t85_comment_handler, NULL);
  288. result = t85_decode_put(&t85_dec, data, total_len);
  289. if (result == T4_DECODE_MORE_DATA)
  290. result = t85_decode_put(&t85_dec, NULL, 0);
  291. len = t85_decode_get_compressed_image_size(&t85_dec);
  292. printf("Compressed image is %d bytes, %d rows\n", len/8, write_row);
  293. t85_decode_release(&t85_dec);
  294. return 0;
  295. case COMPRESSION_T43:
  296. printf("T.43 image %ld bytes\n", (long int) total_len);
  297. if (pack_16(data) == 0xFFA8)
  298. {
  299. data += 2;
  300. total_len -= 2;
  301. for (;;)
  302. {
  303. if (pack_16(data) == 0xFFE1)
  304. {
  305. data += 2;
  306. total_len -= 2;
  307. len = pack_16(data);
  308. data += len;
  309. total_len -= len;
  310. }
  311. else if (pack_16(data) == 0xFFE3)
  312. {
  313. data += 2;
  314. total_len -= 2;
  315. len = pack_32(data);
  316. data += len;
  317. total_len -= len;
  318. }
  319. else
  320. {
  321. break;
  322. }
  323. }
  324. }
  325. bit_mask = 0x80;
  326. t85_decode_init(&t85_dec, t85_row_write_handler, NULL);
  327. t85_decode_set_comment_handler(&t85_dec, 1000, t85_comment_handler, NULL);
  328. t85_dec.min_bit_planes = 1;
  329. t85_dec.max_bit_planes = 8;
  330. data5_ptr = 0;
  331. result = t85_decode_put(&t85_dec, data, total_len);
  332. len = t85_decode_get_compressed_image_size(&t85_dec);
  333. printf("Compressed image is %d bytes, %d rows\n", len/8, write_row);
  334. for (j = 1; j < t85_dec.bit_planes; j++)
  335. {
  336. bit_mask >>= 1;
  337. data += len/8;
  338. total_len -= len/8;
  339. t85_decode_new_plane(&t85_dec);
  340. data5_ptr = 0;
  341. t85_decode_set_comment_handler(&t85_dec, 1000, t85_comment_handler, NULL);
  342. result = t85_decode_put(&t85_dec, data, total_len);
  343. len = t85_decode_get_compressed_image_size(&t85_dec);
  344. printf("Compressed image is %d bytes, %d rows\n", len/8, write_row);
  345. }
  346. if (result == T4_DECODE_MORE_DATA)
  347. {
  348. printf("More\n");
  349. result = t85_decode_put(&t85_dec, NULL, 0);
  350. }
  351. len = t85_decode_get_compressed_image_size(&t85_dec);
  352. printf("Compressed image is %d bytes, %d rows\n", len/8, write_row);
  353. t85_decode_release(&t85_dec);
  354. for (j = 0; j < data5_ptr; j += 3)
  355. {
  356. i = data5[j] & 0xFF;
  357. //printf("%d %d %d %d %d %d\n", data5_ptr, j, i, colour_map[3*i], colour_map[3*i + 1], colour_map[3*i + 2]);
  358. data5[j] = colour_map[3*i];
  359. data5[j + 1] = colour_map[3*i + 1];
  360. data5[j + 2] = colour_map[3*i + 2];
  361. }
  362. if ((tif = TIFFOpen(OUT_FILE_NAME, "w")) == NULL)
  363. {
  364. printf("Unable to open '%s'!\n", OUT_FILE_NAME);
  365. return 1;
  366. }
  367. TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
  368. TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
  369. // libtiff requires IMAGELENGTH to be set before SAMPLESPERPIXEL,
  370. // or StripOffsets and StripByteCounts will have SAMPLESPERPIXEL values
  371. TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
  372. TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
  373. TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
  374. TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
  375. TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  376. TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  377. TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, (uint32) -1);
  378. TIFFSetField(tif, TIFFTAG_XRESOLUTION, 200.0f);
  379. TIFFSetField(tif, TIFFTAG_YRESOLUTION, 200.0f);
  380. TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  381. TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp");
  382. TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test");
  383. TIFFSetField(tif, TIFFTAG_DATETIME, "2012/07/03 12:30:45");
  384. TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org");
  385. TIFFSetField(tif, TIFFTAG_MODEL, "spandsp");
  386. TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org");
  387. for (off = 0, i = 0; i < h; off += w*3, i++)
  388. {
  389. TIFFWriteScanline(tif, data5 + off, i, 0);
  390. }
  391. TIFFWriteDirectory(tif);
  392. TIFFClose(tif);
  393. return 0;
  394. case COMPRESSION_JPEG:
  395. break;
  396. }
  397. }
  398. else
  399. {
  400. printf("Width %d, height %d, bits %d, samples %d\n", w, h, bits_per_pixel, samples_per_pixel);
  401. bytes_per_row = (bits_per_pixel + 7)/8;
  402. bytes_per_row *= w*samples_per_pixel;
  403. totdata = h*bytes_per_row;
  404. printf("total %d\n", totdata);
  405. /* Read the image into memory. */
  406. if ((data = malloc(totdata)) == NULL)
  407. {
  408. printf("Failed to allocate buffer\n");
  409. exit(2);
  410. }
  411. off = 0;
  412. for (row = 0; row < h; row++)
  413. {
  414. if (TIFFReadScanline(tif, data + off, row, 0) < 0)
  415. return 1;
  416. off += bytes_per_row;
  417. }
  418. printf("total %u, off %ld\n", totdata, (long int) off);
  419. /* We now have the image in memory in RGB form */
  420. if (photometric == PHOTOMETRIC_ITULAB)
  421. {
  422. printf("YYY ITULAB\n");
  423. #if 0
  424. if (!t42_itulab_to_itulab(logging, (tdata_t) &outptr, &outsize, data, off, w, h, 3))
  425. {
  426. printf("Failed to convert to ITULAB\n");
  427. return 1;
  428. }
  429. #else
  430. outptr = 0;
  431. #endif
  432. free(data);
  433. data = (uint8_t *) outptr;
  434. off = outsize;
  435. }
  436. else
  437. {
  438. start = rdtscll();
  439. switch (photometric)
  440. {
  441. case PHOTOMETRIC_CIELAB:
  442. printf("CIELAB\n");
  443. /* The default luminant is D50 */
  444. set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f);
  445. set_lab_gamut(&lab_param, 0, 100, -128, 127, -128, 127, true);
  446. lab_to_srgb(&lab_param, data, data, w*h);
  447. break;
  448. case PHOTOMETRIC_ITULAB:
  449. /* The default luminant is D50 */
  450. set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f);
  451. set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, false);
  452. break;
  453. }
  454. //if (!t42_srgb_to_itulab_jpeg(logging, &lab_param, (tdata_t) &outptr, &outsize, data, off, w, h, 3))
  455. {
  456. printf("Failed to convert to ITULAB\n");
  457. return 1;
  458. }
  459. end = rdtscll();
  460. printf("Duration %" PRIu64 "\n", end - start);
  461. free(data);
  462. data = (uint8_t *) outptr;
  463. off = outsize;
  464. }
  465. }
  466. TIFFClose(tif);
  467. printf("XXX - image is %d by %d, %ld bytes\n", w, h, (long int) off);
  468. /* We now have the image in memory in ITULAB form */
  469. if ((tif = TIFFOpen(OUT_FILE_NAME, "w")) == NULL)
  470. {
  471. printf("Unable to open '%s'!\n", OUT_FILE_NAME);
  472. return 1;
  473. }
  474. TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
  475. TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
  476. /* libtiff requires IMAGELENGTH to be set before SAMPLESPERPIXEL,
  477. or StripOffsets and StripByteCounts will have SAMPLESPERPIXEL values */
  478. TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
  479. TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
  480. TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
  481. TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
  482. TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  483. TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  484. TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, (uint32) -1);
  485. TIFFSetField(tif, TIFFTAG_XRESOLUTION, 200.0f);
  486. TIFFSetField(tif, TIFFTAG_YRESOLUTION, 200.0f);
  487. TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  488. TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp");
  489. TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test");
  490. TIFFSetField(tif, TIFFTAG_DATETIME, "2012/07/03 12:30:45");
  491. TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org");
  492. TIFFSetField(tif, TIFFTAG_MODEL, "spandsp");
  493. TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org");
  494. if (1)
  495. {
  496. /* Most image processors won't know what to do with the ITULAB colorspace.
  497. So we'll be converting it to RGB for portability. */
  498. #if 1
  499. TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
  500. #else
  501. TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
  502. #endif
  503. if (YCbCrSubsampleHoriz || YCbCrSubsampleVert)
  504. TIFFSetField(tif, TIFFTAG_YCBCRSUBSAMPLING, YCbCrSubsampleHoriz, YCbCrSubsampleVert);
  505. bytes_per_row = (bits_per_pixel + 7)/8;
  506. bytes_per_row *= w*samples_per_pixel;
  507. totdata = h*bytes_per_row;
  508. /* The default luminant is D50 */
  509. set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f);
  510. set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, false);
  511. #if 0
  512. start = rdtscll();
  513. data2 = NULL;
  514. totdata = 0;
  515. t42_itulab_to_jpeg(logging, &lab_param, (void **) &data2, &totdata, data, off);
  516. end = rdtscll();
  517. printf("Duration %" PRIu64 "\n", end - start);
  518. printf("Compressed length %d (%p)\n", totdata, data2);
  519. if (TIFFWriteRawStrip(tif, 0, data2, totdata) < 0)
  520. {
  521. printf("Failed to convert from ITULAB\n");
  522. return 1;
  523. }
  524. free(data);
  525. #else
  526. if ((data2 = malloc(totdata)) == NULL)
  527. {
  528. printf("Failed to allocate buffer\n");
  529. exit(2);
  530. }
  531. start = rdtscll();
  532. //if (!t42_itulab_jpeg_to_srgb(logging, &lab_param, data2, &off, data, off, &w, &h, &samples_per_pixel))
  533. {
  534. printf("Failed to convert from ITULAB\n");
  535. return 1;
  536. }
  537. end = rdtscll();
  538. printf("Duration %" PRIu64 "\n", end - start);
  539. free(data);
  540. off = 0;
  541. bytes_per_row = (8 + 7)/8;
  542. bytes_per_row *= (w*3);
  543. for (row = 0; row < h; row++)
  544. {
  545. if (TIFFWriteScanline(tif, data2 + off, row, 0) < 0)
  546. return 1;
  547. off += bytes_per_row;
  548. }
  549. #endif
  550. free(data2);
  551. }
  552. else
  553. {
  554. #if 1
  555. /* If PHOTOMETRIC_ITULAB is not available the admin cannot enable color fax anyway.
  556. This is done so that older libtiffs without it can build fine. */
  557. TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ITULAB);
  558. #else
  559. TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
  560. #endif
  561. if (YCbCrSubsampleHoriz || YCbCrSubsampleVert)
  562. TIFFSetField(tif, TIFFTAG_YCBCRSUBSAMPLING, YCbCrSubsampleHoriz, YCbCrSubsampleVert);
  563. if (TIFFWriteRawStrip(tif, 0, (tdata_t) data, off) == -1)
  564. {
  565. printf("Write error to TIFF file\n");
  566. return 1;
  567. }
  568. free(data);
  569. }
  570. TIFFWriteDirectory(tif);
  571. TIFFClose(tif);
  572. printf("Done!\n");
  573. return 0;
  574. }
  575. /*- End of function --------------------------------------------------------*/
  576. /*- End of file ------------------------------------------------------------*/