6 /* needed to implement our substitute TIFFIsCODECConfigured */
7 #if TIFFLIB_VERSION < 20031121
8 static int TIFFIsCODECConfigured(uint16 scheme);
14 tiff.c - implements reading and writing tiff files, uses io layer.
18 io_glue *ig = io_new_fd( fd );
19 i_img *im = i_readtiff_wiol(ig, -1); // no limit on how much is read
21 io_glue *ig = io_new_fd( fd );
22 return_code = i_writetiff_wiol(im, ig);
26 tiff.c implements the basic functions to read and write tiff files.
27 It uses the iolayer and needs either a seekable source or an entire
30 =head1 FUNCTION REFERENCE
32 Some of these functions are internal.
39 #define byteswap_macro(x) \
40 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
41 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
43 #define CLAMP8(x) ((x) < 0 ? 0 : (x) > 255 ? 255 : (x))
44 #define CLAMP16(x) ((x) < 0 ? 0 : (x) > 65535 ? 65535 : (x))
46 #define Sample16To8(num) ((num) / 257)
53 static i_img *read_one_rgb_tiled(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete);
54 static i_img *read_one_rgb_lines(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete);
56 static struct tag_name text_tag_names[] =
58 { "tiff_documentname", TIFFTAG_DOCUMENTNAME, },
59 { "tiff_imagedescription", TIFFTAG_IMAGEDESCRIPTION, },
60 { "tiff_make", TIFFTAG_MAKE, },
61 { "tiff_model", TIFFTAG_MODEL, },
62 { "tiff_pagename", TIFFTAG_PAGENAME, },
63 { "tiff_software", TIFFTAG_SOFTWARE, },
64 { "tiff_datetime", TIFFTAG_DATETIME, },
65 { "tiff_artist", TIFFTAG_ARTIST, },
66 { "tiff_hostcomputer", TIFFTAG_HOSTCOMPUTER, },
69 static struct tag_name
72 { "none", COMPRESSION_NONE },
73 { "ccittrle", COMPRESSION_CCITTRLE },
74 { "fax3", COMPRESSION_CCITTFAX3 },
75 { "t4", COMPRESSION_CCITTFAX3 },
76 { "fax4", COMPRESSION_CCITTFAX4 },
77 { "t6", COMPRESSION_CCITTFAX4 },
78 { "lzw", COMPRESSION_LZW },
79 { "jpeg", COMPRESSION_JPEG },
80 { "packbits", COMPRESSION_PACKBITS },
81 { "deflate", COMPRESSION_ADOBE_DEFLATE },
82 { "zip", COMPRESSION_ADOBE_DEFLATE },
83 { "oldzip", COMPRESSION_DEFLATE },
84 { "ccittrlew", COMPRESSION_CCITTRLEW },
87 static const int compress_value_count =
88 sizeof(compress_values) / sizeof(*compress_values);
91 myTIFFIsCODECConfigured(uint16 scheme);
93 typedef struct read_state_tag read_state_t;
94 /* the setup function creates the image object, allocates the line buffer */
95 typedef int (*read_setup_t)(read_state_t *state);
97 /* the putter writes the image data provided by the getter to the
98 image, x, y, width, height describe the target area of the image,
99 extras is the extra number of pixels stored for each scanline in
100 the raster buffer, (for tiles against the right side of the
103 typedef int (*read_putter_t)(read_state_t *state, i_img_dim x, i_img_dim y,
104 i_img_dim width, i_img_dim height, int extras);
106 /* reads from a tiled or strip image and calls the putter.
107 This may need a second type for handling non-contiguous images
109 typedef int (*read_getter_t)(read_state_t *state, read_putter_t putter);
111 struct read_state_tag {
115 i_img_dim pixels_read;
116 int allow_incomplete;
118 uint32 width, height;
119 uint16 bits_per_sample;
122 /* the total number of channels (samples per pixel) */
123 int samples_per_pixel;
125 /* if non-zero, which channel is the alpha channel, typically 3 for rgb */
128 /* whether or not to scale the color channels based on the alpha
129 channel. TIFF has 2 types of alpha channel, if the alpha channel
130 we use is EXTRASAMPLE_ASSOCALPHA then the color data will need to
131 be scaled to match Imager's conventions */
135 static int tile_contig_getter(read_state_t *state, read_putter_t putter);
136 static int strip_contig_getter(read_state_t *state, read_putter_t putter);
138 static int setup_paletted(read_state_t *state);
139 static int paletted_putter8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
140 static int paletted_putter4(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
142 static int setup_16_rgb(read_state_t *state);
143 static int setup_16_grey(read_state_t *state);
144 static int putter_16(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
146 static int setup_8_rgb(read_state_t *state);
147 static int setup_8_grey(read_state_t *state);
148 static int putter_8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
150 static int setup_32_rgb(read_state_t *state);
151 static int setup_32_grey(read_state_t *state);
152 static int putter_32(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
154 static int setup_bilevel(read_state_t *state);
155 static int putter_bilevel(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
157 static int setup_cmyk8(read_state_t *state);
158 static int putter_cmyk8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
160 static int setup_cmyk16(read_state_t *state);
161 static int putter_cmyk16(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
163 rgb_channels(read_state_t *state, int *out_channels);
165 grey_channels(read_state_t *state, int *out_channels);
167 cmyk_channels(read_state_t *state, int *out_channels);
169 fallback_rgb_channels(TIFF *tif, i_img_dim width, i_img_dim height, int *channels, int *alpha_chan);
171 static const int text_tag_count =
172 sizeof(text_tag_names) / sizeof(*text_tag_names);
174 #if TIFFLIB_VERSION >= 20051230
175 #define USE_EXT_WARN_HANDLER
178 #define TIFFIO_MAGIC 0xC6A340CC
180 static void error_handler(char const *module, char const *fmt, va_list ap) {
181 mm_log((1, "tiff error fmt %s\n", fmt));
182 i_push_errorvf(0, fmt, ap);
188 #ifdef USE_EXT_WARN_HANDLER
195 tiffio_context_init(tiffio_context_t *c, io_glue *ig);
197 tiffio_context_final(tiffio_context_t *c);
199 #define WARN_BUFFER_LIMIT 10000
201 #ifdef USE_EXT_WARN_HANDLER
204 warn_handler_ex(thandle_t h, const char *module, const char *fmt, va_list ap) {
205 tiffio_context_t *c = (tiffio_context_t *)h;
208 if (c->magic != TIFFIO_MAGIC)
212 #ifdef IMAGER_VSNPRINTF
213 vsnprintf(buf, sizeof(buf), fmt, ap);
215 vsprintf(buf, fmt, ap);
217 mm_log((1, "tiff warning %s\n", buf));
219 if (!c->warn_buffer || strlen(c->warn_buffer)+strlen(buf)+2 > c->warn_size) {
220 size_t new_size = c->warn_size + strlen(buf) + 2;
221 char *old_buffer = c->warn_buffer;
222 if (new_size > WARN_BUFFER_LIMIT) {
223 new_size = WARN_BUFFER_LIMIT;
225 c->warn_buffer = myrealloc(c->warn_buffer, new_size);
226 if (!old_buffer) c->warn_buffer[0] = '\0';
227 c->warn_size = new_size;
229 if (strlen(c->warn_buffer)+strlen(buf)+2 <= c->warn_size) {
230 strcat(c->warn_buffer, buf);
231 strcat(c->warn_buffer, "\n");
237 static char *warn_buffer = NULL;
238 static int warn_buffer_size = 0;
240 static void warn_handler(char const *module, char const *fmt, va_list ap) {
244 #ifdef IMAGER_VSNPRINTF
245 vsnprintf(buf, sizeof(buf), fmt, ap);
247 vsprintf(buf, fmt, ap);
249 mm_log((1, "tiff warning %s\n", buf));
251 if (!warn_buffer || strlen(warn_buffer)+strlen(buf)+2 > warn_buffer_size) {
252 int new_size = warn_buffer_size + strlen(buf) + 2;
253 char *old_buffer = warn_buffer;
254 if (new_size > WARN_BUFFER_LIMIT) {
255 new_size = WARN_BUFFER_LIMIT;
257 warn_buffer = myrealloc(warn_buffer, new_size);
258 if (!old_buffer) *warn_buffer = '\0';
259 warn_buffer_size = new_size;
261 if (strlen(warn_buffer)+strlen(buf)+2 <= warn_buffer_size) {
262 strcat(warn_buffer, buf);
263 strcat(warn_buffer, "\n");
269 static i_mutex_t mutex;
273 mutex = i_mutex_new();
276 static int save_tiff_tags(TIFF *tif, i_img *im);
279 pack_4bit_to(unsigned char *dest, const unsigned char *src, i_img_dim count);
282 static toff_t sizeproc(thandle_t x) {
288 =item comp_seek(h, o, w)
290 Compatability for 64 bit systems like latest freebsd (internal)
292 h - tiff handle, cast an io_glue object
301 comp_seek(thandle_t h, toff_t o, int w) {
302 io_glue *ig = ((tiffio_context_t *)h)->ig;
303 return (toff_t) i_io_seek(ig, o, w);
307 =item comp_mmap(thandle_t, tdata_t*, toff_t*)
311 This shouldn't ever be called but newer tifflibs want it anyway.
318 comp_mmap(thandle_t h, tdata_t*p, toff_t*off) {
323 =item comp_munmap(thandle_t h, tdata_t p, toff_t off)
327 This shouldn't ever be called but newer tifflibs want it anyway.
333 comp_munmap(thandle_t h, tdata_t p, toff_t off) {
338 comp_read(thandle_t h, tdata_t p, tsize_t size) {
339 return i_io_read(((tiffio_context_t *)h)->ig, p, size);
343 comp_write(thandle_t h, tdata_t p, tsize_t size) {
344 return i_io_write(((tiffio_context_t *)h)->ig, p, size);
348 comp_close(thandle_t h) {
349 return i_io_close(((tiffio_context_t *)h)->ig);
352 static i_img *read_one_tiff(TIFF *tif, int allow_incomplete) {
354 uint32 width, height;
355 uint16 samples_per_pixel;
359 int gotXres, gotYres;
361 uint16 bits_per_sample;
362 uint16 planar_config;
367 read_setup_t setupf = NULL;
368 read_getter_t getterf = NULL;
369 read_putter_t putterf = NULL;
370 int channels = MAXCHANNELS;
371 size_t sample_size = ~0; /* force failure if some code doesn't set it */
372 i_img_dim total_pixels;
376 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
377 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
378 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
379 tiled = TIFFIsTiled(tif);
380 TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
381 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
382 TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config);
383 TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
385 mm_log((1, "i_readtiff_wiol: width=%d, height=%d, channels=%d\n", width, height, samples_per_pixel));
386 mm_log((1, "i_readtiff_wiol: %stiled\n", tiled?"":"not "));
387 mm_log((1, "i_readtiff_wiol: %sbyte swapped\n", TIFFIsByteSwapped(tif)?"":"not "));
389 total_pixels = width * height;
390 memset(&state, 0, sizeof(state));
392 state.allow_incomplete = allow_incomplete;
394 state.height = height;
395 state.bits_per_sample = bits_per_sample;
396 state.samples_per_pixel = samples_per_pixel;
397 state.photometric = photometric;
399 /* yes, this if() is horrible */
400 if (photometric == PHOTOMETRIC_PALETTE && bits_per_sample <= 8) {
401 setupf = setup_paletted;
402 if (bits_per_sample == 8)
403 putterf = paletted_putter8;
404 else if (bits_per_sample == 4)
405 putterf = paletted_putter4;
407 mm_log((1, "unsupported paletted bits_per_sample %d\n", bits_per_sample));
409 sample_size = sizeof(i_sample_t);
412 else if (bits_per_sample == 16
413 && photometric == PHOTOMETRIC_RGB
414 && samples_per_pixel >= 3) {
415 setupf = setup_16_rgb;
418 rgb_channels(&state, &channels);
420 else if (bits_per_sample == 16
421 && photometric == PHOTOMETRIC_MINISBLACK) {
422 setupf = setup_16_grey;
425 grey_channels(&state, &channels);
427 else if (bits_per_sample == 8
428 && photometric == PHOTOMETRIC_MINISBLACK) {
429 setupf = setup_8_grey;
432 grey_channels(&state, &channels);
434 else if (bits_per_sample == 8
435 && photometric == PHOTOMETRIC_RGB) {
436 setupf = setup_8_rgb;
439 rgb_channels(&state, &channels);
441 else if (bits_per_sample == 32
442 && photometric == PHOTOMETRIC_RGB
443 && samples_per_pixel >= 3) {
444 setupf = setup_32_rgb;
446 sample_size = sizeof(i_fsample_t);
447 rgb_channels(&state, &channels);
449 else if (bits_per_sample == 32
450 && photometric == PHOTOMETRIC_MINISBLACK) {
451 setupf = setup_32_grey;
453 sample_size = sizeof(i_fsample_t);
454 grey_channels(&state, &channels);
456 else if (bits_per_sample == 1
457 && (photometric == PHOTOMETRIC_MINISBLACK
458 || photometric == PHOTOMETRIC_MINISWHITE)
459 && samples_per_pixel == 1) {
460 setupf = setup_bilevel;
461 putterf = putter_bilevel;
462 sample_size = sizeof(i_palidx);
465 else if (bits_per_sample == 8
466 && photometric == PHOTOMETRIC_SEPARATED
467 && inkset == INKSET_CMYK
468 && samples_per_pixel >= 4) {
469 setupf = setup_cmyk8;
470 putterf = putter_cmyk8;
472 cmyk_channels(&state, &channels);
474 else if (bits_per_sample == 16
475 && photometric == PHOTOMETRIC_SEPARATED
476 && inkset == INKSET_CMYK
477 && samples_per_pixel >= 4) {
478 setupf = setup_cmyk16;
479 putterf = putter_cmyk16;
481 cmyk_channels(&state, &channels);
485 fallback_rgb_channels(tif, width, height, &channels, &alpha);
489 if (!i_int_check_image_file_limits(width, height, channels, sample_size)) {
494 if (planar_config == PLANARCONFIG_CONTIG)
495 getterf = tile_contig_getter;
498 if (planar_config == PLANARCONFIG_CONTIG)
499 getterf = strip_contig_getter;
501 if (setupf && getterf && putterf) {
505 if (!getterf(&state, putterf) || !state.pixels_read) {
507 i_img_destroy(state.img);
509 _TIFFfree(state.raster);
511 myfree(state.line_buf);
516 if (allow_incomplete && state.pixels_read < total_pixels) {
517 i_tags_setn(&(state.img->tags), "i_incomplete", 1);
518 i_tags_setn(&(state.img->tags), "i_lines_read",
519 state.pixels_read / width);
524 _TIFFfree(state.raster);
526 myfree(state.line_buf);
530 im = read_one_rgb_tiled(tif, width, height, allow_incomplete);
533 im = read_one_rgb_lines(tif, width, height, allow_incomplete);
540 /* general metadata */
541 i_tags_setn(&im->tags, "tiff_bitspersample", bits_per_sample);
542 i_tags_setn(&im->tags, "tiff_photometric", photometric);
543 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
545 /* resolution tags */
546 TIFFGetFieldDefaulted(tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
547 gotXres = TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres);
548 gotYres = TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres);
549 if (gotXres || gotYres) {
554 i_tags_setn(&im->tags, "tiff_resolutionunit", resunit);
555 if (resunit == RESUNIT_CENTIMETER) {
556 /* from dots per cm to dpi */
559 i_tags_set(&im->tags, "tiff_resolutionunit_name", "centimeter", -1);
561 else if (resunit == RESUNIT_NONE) {
562 i_tags_setn(&im->tags, "i_aspect_only", 1);
563 i_tags_set(&im->tags, "tiff_resolutionunit_name", "none", -1);
565 else if (resunit == RESUNIT_INCH) {
566 i_tags_set(&im->tags, "tiff_resolutionunit_name", "inch", -1);
569 i_tags_set(&im->tags, "tiff_resolutionunit_name", "unknown", -1);
571 /* tifflib doesn't seem to provide a way to get to the original rational
572 value of these, which would let me provide a more reasonable
573 precision. So make up a number. */
574 i_tags_set_float2(&im->tags, "i_xres", 0, xres, 6);
575 i_tags_set_float2(&im->tags, "i_yres", 0, yres, 6);
579 for (i = 0; i < text_tag_count; ++i) {
581 if (TIFFGetField(tif, text_tag_names[i].tag, &data)) {
582 mm_log((1, "i_readtiff_wiol: tag %d has value %s\n",
583 text_tag_names[i].tag, data));
584 i_tags_set(&im->tags, text_tag_names[i].name, data, -1);
588 i_tags_set(&im->tags, "i_format", "tiff", 4);
589 #ifdef USE_EXT_WARN_HANDLER
591 tiffio_context_t *ctx = TIFFClientdata(tif);
592 if (ctx->warn_buffer && ctx->warn_buffer[0]) {
593 i_tags_set(&im->tags, "i_warning", ctx->warn_buffer, -1);
594 ctx->warn_buffer[0] = '\0';
598 if (warn_buffer && *warn_buffer) {
599 i_tags_set(&im->tags, "i_warning", warn_buffer, -1);
604 for (i = 0; i < compress_value_count; ++i) {
605 if (compress_values[i].tag == compress) {
606 i_tags_set(&im->tags, "tiff_compression", compress_values[i].name, -1);
615 =item i_readtiff_wiol(im, ig)
620 i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
622 TIFFErrorHandler old_handler;
623 TIFFErrorHandler old_warn_handler;
624 #ifdef USE_EXT_WARN_HANDLER
625 TIFFErrorHandlerExt old_ext_warn_handler;
629 tiffio_context_t ctx;
634 old_handler = TIFFSetErrorHandler(error_handler);
635 #ifdef USE_EXT_WARN_HANDLER
636 old_warn_handler = TIFFSetWarningHandler(NULL);
637 old_ext_warn_handler = TIFFSetWarningHandlerExt(warn_handler_ex);
639 old_warn_handler = TIFFSetWarningHandler(warn_handler);
644 /* Add code to get the filename info from the iolayer */
645 /* Also add code to check for mmapped code */
647 mm_log((1, "i_readtiff_wiol(ig %p, allow_incomplete %d, page %d)\n", ig, allow_incomplete, page));
649 tiffio_context_init(&ctx, ig);
650 tif = TIFFClientOpen("(Iolayer)",
662 mm_log((1, "i_readtiff_wiol: Unable to open tif file\n"));
663 i_push_error(0, "Error opening file");
664 TIFFSetErrorHandler(old_handler);
665 TIFFSetWarningHandler(old_warn_handler);
666 #ifdef USE_EXT_WARN_HANDLER
667 TIFFSetWarningHandlerExt(old_ext_warn_handler);
669 tiffio_context_final(&ctx);
670 i_mutex_unlock(mutex);
674 for (current_page = 0; current_page < page; ++current_page) {
675 if (!TIFFReadDirectory(tif)) {
676 mm_log((1, "i_readtiff_wiol: Unable to switch to directory %d\n", page));
677 i_push_errorf(0, "could not switch to page %d", page);
678 TIFFSetErrorHandler(old_handler);
679 TIFFSetWarningHandler(old_warn_handler);
680 #ifdef USE_EXT_WARN_HANDLER
681 TIFFSetWarningHandlerExt(old_ext_warn_handler);
684 tiffio_context_final(&ctx);
685 i_mutex_unlock(mutex);
690 im = read_one_tiff(tif, allow_incomplete);
692 if (TIFFLastDirectory(tif)) mm_log((1, "Last directory of tiff file\n"));
693 TIFFSetErrorHandler(old_handler);
694 TIFFSetWarningHandler(old_warn_handler);
695 #ifdef USE_EXT_WARN_HANDLER
696 TIFFSetWarningHandlerExt(old_ext_warn_handler);
699 tiffio_context_final(&ctx);
700 i_mutex_unlock(mutex);
706 =item i_readtiff_multi_wiol(ig, *count)
708 Reads multiple images from a TIFF.
713 i_readtiff_multi_wiol(io_glue *ig, int *count) {
715 TIFFErrorHandler old_handler;
716 TIFFErrorHandler old_warn_handler;
717 #ifdef USE_EXT_WARN_HANDLER
718 TIFFErrorHandlerExt old_ext_warn_handler;
720 i_img **results = NULL;
721 int result_alloc = 0;
722 tiffio_context_t ctx;
727 old_handler = TIFFSetErrorHandler(error_handler);
728 #ifdef USE_EXT_WARN_HANDLER
729 old_warn_handler = TIFFSetWarningHandler(NULL);
730 old_ext_warn_handler = TIFFSetWarningHandlerExt(warn_handler_ex);
732 old_warn_handler = TIFFSetWarningHandler(warn_handler);
737 tiffio_context_init(&ctx, ig);
739 /* Add code to get the filename info from the iolayer */
740 /* Also add code to check for mmapped code */
742 mm_log((1, "i_readtiff_wiol(ig %p, length %d)\n", ig));
744 tif = TIFFClientOpen("(Iolayer)",
756 mm_log((1, "i_readtiff_wiol: Unable to open tif file\n"));
757 i_push_error(0, "Error opening file");
758 TIFFSetErrorHandler(old_handler);
759 TIFFSetWarningHandler(old_warn_handler);
760 #ifdef USE_EXT_WARN_HANDLER
761 TIFFSetWarningHandlerExt(old_ext_warn_handler);
763 tiffio_context_final(&ctx);
764 i_mutex_unlock(mutex);
770 i_img *im = read_one_tiff(tif, 0);
773 if (++*count > result_alloc) {
774 if (result_alloc == 0) {
776 results = mymalloc(result_alloc * sizeof(i_img *));
781 newresults = myrealloc(results, result_alloc * sizeof(i_img *));
783 i_img_destroy(im); /* don't leak it */
786 results = newresults;
789 results[*count-1] = im;
790 } while (TIFFReadDirectory(tif));
792 TIFFSetWarningHandler(old_warn_handler);
793 TIFFSetErrorHandler(old_handler);
794 #ifdef USE_EXT_WARN_HANDLER
795 TIFFSetWarningHandlerExt(old_ext_warn_handler);
798 tiffio_context_final(&ctx);
799 i_mutex_unlock(mutex);
805 i_writetiff_low_faxable(TIFF *tif, i_img *im, int fine) {
806 uint32 width, height;
807 unsigned char *linebuf = NULL;
812 float vres = fine ? 196 : 98;
818 if (width != im->xsize || height != im->ysize) {
819 i_push_error(0, "image too large for TIFF");
823 switch (im->channels) {
833 /* This means a colorspace we don't handle yet */
834 mm_log((1, "i_writetiff_wiol_faxable: don't handle %d channel images.\n", im->channels));
838 /* Add code to get the filename info from the iolayer */
839 /* Also add code to check for mmapped code */
842 mm_log((1, "i_writetiff_wiol_faxable: width=%d, height=%d, channels=%d\n", width, height, im->channels));
844 if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width) )
845 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField width=%d failed\n", width)); return 0; }
846 if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height) )
847 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField length=%d failed\n", height)); return 0; }
848 if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1))
849 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField samplesperpixel=1 failed\n")); return 0; }
850 if (!TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT))
851 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField Orientation=topleft\n")); return 0; }
852 if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1) )
853 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField bitpersample=1\n")); return 0; }
854 if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG))
855 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField planarconfig\n")); return 0; }
856 if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE))
857 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField photometric=%d\n", PHOTOMETRIC_MINISBLACK)); return 0; }
858 if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, 3))
859 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField compression=3\n")); return 0; }
861 linebuf = (unsigned char *)_TIFFmalloc( TIFFScanlineSize(tif) );
863 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
864 mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField rowsperstrip=-1\n")); return 0; }
866 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
867 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rc);
869 mm_log((1, "i_writetiff_wiol_faxable: TIFFGetField rowsperstrip=%d\n", rowsperstrip));
870 mm_log((1, "i_writetiff_wiol_faxable: TIFFGetField scanlinesize=%d\n", TIFFScanlineSize(tif) ));
871 mm_log((1, "i_writetiff_wiol_faxable: TIFFGetField planarconfig=%d == %d\n", rc, PLANARCONFIG_CONTIG));
873 if (!TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)204))
874 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField Xresolution=204\n")); return 0; }
875 if (!TIFFSetField(tif, TIFFTAG_YRESOLUTION, vres))
876 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField Yresolution=196\n")); return 0; }
877 if (!TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)) {
878 mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField ResolutionUnit=%d\n", RESUNIT_INCH)); return 0;
881 if (!save_tiff_tags(tif, im)) {
885 for (y=0; y<height; y++) {
887 for(x=0; x<width; x+=8) {
892 linebuf[linebufpos]=0;
893 bits = width-x; if(bits>8) bits=8;
894 i_gsamp(im, x, x+8, y, luma, &luma_chan, 1);
895 for(bitpos=0;bitpos<bits;bitpos++) {
896 linebuf[linebufpos] |= ((luma[bitpos] < 128) ? bitval : 0);
901 if (TIFFWriteScanline(tif, linebuf, y, 0) < 0) {
902 mm_log((1, "i_writetiff_wiol_faxable: TIFFWriteScanline failed.\n"));
906 if (linebuf) _TIFFfree(linebuf);
912 find_compression(char const *name, uint16 *compress) {
915 for (i = 0; i < compress_value_count; ++i) {
916 if (strcmp(compress_values[i].name, name) == 0) {
917 *compress = (uint16)compress_values[i].tag;
921 *compress = COMPRESSION_NONE;
927 get_compression(i_img *im, uint16 def_compress) {
931 if (i_tags_find(&im->tags, "tiff_compression", 0, &entry)
932 && im->tags.tags[entry].data) {
934 if (find_compression(im->tags.tags[entry].data, &compress)
935 && myTIFFIsCODECConfigured(compress))
938 if (i_tags_get_int(&im->tags, "tiff_compression", 0, &value)) {
939 if ((uint16)value == value
940 && myTIFFIsCODECConfigured((uint16)value))
941 return (uint16)value;
948 i_tiff_has_compression(const char *name) {
951 if (!find_compression(name, &compress))
954 return myTIFFIsCODECConfigured(compress);
958 set_base_tags(TIFF *tif, i_img *im, uint16 compress, uint16 photometric,
959 uint16 bits_per_sample, uint16 samples_per_pixel) {
962 int got_xres, got_yres;
965 if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, im->xsize)) {
966 i_push_error(0, "write TIFF: setting width tag");
969 if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, im->ysize)) {
970 i_push_error(0, "write TIFF: setting length tag");
973 if (!TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)) {
974 i_push_error(0, "write TIFF: setting orientation tag");
977 if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
978 i_push_error(0, "write TIFF: setting planar configuration tag");
981 if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric)) {
982 i_push_error(0, "write TIFF: setting photometric tag");
985 if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, compress)) {
986 i_push_error(0, "write TIFF: setting compression tag");
989 if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample)) {
990 i_push_error(0, "write TIFF: setting bits per sample tag");
993 if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel)) {
994 i_push_error(0, "write TIFF: setting samples per pixel tag");
998 got_xres = i_tags_get_float(&im->tags, "i_xres", 0, &xres);
999 got_yres = i_tags_get_float(&im->tags, "i_yres", 0, &yres);
1000 if (!i_tags_get_int(&im->tags, "i_aspect_only", 0,&aspect_only))
1002 if (!i_tags_get_int(&im->tags, "tiff_resolutionunit", 0, &resunit))
1003 resunit = RESUNIT_INCH;
1004 if (got_xres || got_yres) {
1010 resunit = RESUNIT_NONE;
1013 if (resunit == RESUNIT_CENTIMETER) {
1018 resunit = RESUNIT_INCH;
1021 if (!TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)xres)) {
1022 i_push_error(0, "write TIFF: setting xresolution tag");
1025 if (!TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)yres)) {
1026 i_push_error(0, "write TIFF: setting yresolution tag");
1029 if (!TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (uint16)resunit)) {
1030 i_push_error(0, "write TIFF: setting resolutionunit tag");
1039 write_one_bilevel(TIFF *tif, i_img *im, int zero_is_white) {
1040 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1042 unsigned char *in_row;
1043 unsigned char *out_row;
1048 mm_log((1, "tiff - write_one_bilevel(tif %p, im %p, zero_is_white %d)\n",
1049 tif, im, zero_is_white));
1051 /* ignore a silly choice */
1052 if (compress == COMPRESSION_JPEG)
1053 compress = COMPRESSION_PACKBITS;
1056 case COMPRESSION_CCITTRLE:
1057 case COMPRESSION_CCITTFAX3:
1058 case COMPRESSION_CCITTFAX4:
1059 /* natural fax photometric */
1060 photometric = PHOTOMETRIC_MINISWHITE;
1064 /* natural for most computer images */
1065 photometric = PHOTOMETRIC_MINISBLACK;
1069 if (!set_base_tags(tif, im, compress, photometric, 1, 1))
1072 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
1073 i_push_error(0, "write TIFF: setting rows per strip tag");
1077 out_size = TIFFScanlineSize(tif);
1078 out_row = (unsigned char *)_TIFFmalloc( out_size );
1079 in_row = mymalloc(im->xsize);
1081 invert = (photometric == PHOTOMETRIC_MINISWHITE) != (zero_is_white != 0);
1083 for (y = 0; y < im->ysize; ++y) {
1085 unsigned char *outp = out_row;
1086 memset(out_row, 0, out_size);
1087 i_gpal(im, 0, im->xsize, y, in_row);
1088 for (x = 0; x < im->xsize; ++x) {
1089 if (invert ? !in_row[x] : in_row[x]) {
1098 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1101 i_push_error(0, "write TIFF: write scan line failed");
1113 set_palette(TIFF *tif, i_img *im, int size) {
1120 colors = (uint16 *)_TIFFmalloc(sizeof(uint16) * 3 * size);
1122 out[1] = colors + size;
1123 out[2] = colors + 2 * size;
1125 count = i_colorcount(im);
1126 for (i = 0; i < count; ++i) {
1127 i_getcolors(im, i, &c, 1);
1128 for (ch = 0; ch < 3; ++ch)
1129 out[ch][i] = c.channel[ch] * 257;
1131 for (; i < size; ++i) {
1132 for (ch = 0; ch < 3; ++ch)
1135 if (!TIFFSetField(tif, TIFFTAG_COLORMAP, out[0], out[1], out[2])) {
1137 i_push_error(0, "write TIFF: setting color map");
1146 write_one_paletted8(TIFF *tif, i_img *im) {
1147 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1148 unsigned char *out_row;
1152 mm_log((1, "tiff - write_one_paletted8(tif %p, im %p)\n", tif, im));
1154 /* ignore a silly choice */
1155 if (compress == COMPRESSION_JPEG ||
1156 compress == COMPRESSION_CCITTRLE ||
1157 compress == COMPRESSION_CCITTFAX3 ||
1158 compress == COMPRESSION_CCITTFAX4)
1159 compress = COMPRESSION_PACKBITS;
1161 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
1162 i_push_error(0, "write TIFF: setting rows per strip tag");
1166 if (!set_base_tags(tif, im, compress, PHOTOMETRIC_PALETTE, 8, 1))
1169 if (!set_palette(tif, im, 256))
1172 out_size = TIFFScanlineSize(tif);
1173 out_row = (unsigned char *)_TIFFmalloc( out_size );
1175 for (y = 0; y < im->ysize; ++y) {
1176 i_gpal(im, 0, im->xsize, y, out_row);
1177 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1179 i_push_error(0, "write TIFF: write scan line failed");
1190 write_one_paletted4(TIFF *tif, i_img *im) {
1191 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1192 unsigned char *in_row;
1193 unsigned char *out_row;
1197 mm_log((1, "tiff - write_one_paletted4(tif %p, im %p)\n", tif, im));
1199 /* ignore a silly choice */
1200 if (compress == COMPRESSION_JPEG ||
1201 compress == COMPRESSION_CCITTRLE ||
1202 compress == COMPRESSION_CCITTFAX3 ||
1203 compress == COMPRESSION_CCITTFAX4)
1204 compress = COMPRESSION_PACKBITS;
1206 if (!set_base_tags(tif, im, compress, PHOTOMETRIC_PALETTE, 4, 1))
1209 if (!set_palette(tif, im, 16))
1212 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
1213 i_push_error(0, "write TIFF: setting rows per strip tag");
1217 in_row = mymalloc(im->xsize);
1218 out_size = TIFFScanlineSize(tif);
1219 out_row = (unsigned char *)_TIFFmalloc( out_size );
1221 for (y = 0; y < im->ysize; ++y) {
1222 i_gpal(im, 0, im->xsize, y, in_row);
1223 memset(out_row, 0, out_size);
1224 pack_4bit_to(out_row, in_row, im->xsize);
1225 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1227 i_push_error(0, "write TIFF: write scan line failed");
1239 set_direct_tags(TIFF *tif, i_img *im, uint16 compress,
1240 uint16 bits_per_sample) {
1241 uint16 extras = EXTRASAMPLE_ASSOCALPHA;
1242 uint16 extra_count = im->channels == 2 || im->channels == 4;
1243 uint16 photometric = im->channels >= 3 ?
1244 PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
1246 if (!set_base_tags(tif, im, compress, photometric, bits_per_sample,
1252 if (!TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, extra_count, &extras)) {
1253 i_push_error(0, "write TIFF: setting extra samples tag");
1258 if (compress == COMPRESSION_JPEG) {
1260 if (i_tags_get_int(&im->tags, "tiff_jpegquality", 0, &jpeg_quality)
1261 && jpeg_quality >= 0 && jpeg_quality <= 100) {
1262 if (!TIFFSetField(tif, TIFFTAG_JPEGQUALITY, jpeg_quality)) {
1263 i_push_error(0, "write TIFF: setting jpeg quality pseudo-tag");
1273 write_one_32(TIFF *tif, i_img *im) {
1274 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1279 size_t sample_count = im->xsize * im->channels;
1280 size_t sample_index;
1282 mm_log((1, "tiff - write_one_32(tif %p, im %p)\n", tif, im));
1284 /* only 8 and 12 bit samples are supported by jpeg compression */
1285 if (compress == COMPRESSION_JPEG)
1286 compress = COMPRESSION_PACKBITS;
1288 if (!set_direct_tags(tif, im, compress, 32))
1291 in_row = mymalloc(sample_count * sizeof(unsigned));
1292 out_size = TIFFScanlineSize(tif);
1293 out_row = (uint32 *)_TIFFmalloc( out_size );
1295 for (y = 0; y < im->ysize; ++y) {
1296 if (i_gsamp_bits(im, 0, im->xsize, y, in_row, NULL, im->channels, 32) <= 0) {
1297 i_push_error(0, "Cannot read 32-bit samples");
1300 for (sample_index = 0; sample_index < sample_count; ++sample_index)
1301 out_row[sample_index] = in_row[sample_index];
1302 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1305 i_push_error(0, "write TIFF: write scan line failed");
1317 write_one_16(TIFF *tif, i_img *im) {
1318 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1323 size_t sample_count = im->xsize * im->channels;
1324 size_t sample_index;
1326 mm_log((1, "tiff - write_one_16(tif %p, im %p)\n", tif, im));
1328 /* only 8 and 12 bit samples are supported by jpeg compression */
1329 if (compress == COMPRESSION_JPEG)
1330 compress = COMPRESSION_PACKBITS;
1332 if (!set_direct_tags(tif, im, compress, 16))
1335 in_row = mymalloc(sample_count * sizeof(unsigned));
1336 out_size = TIFFScanlineSize(tif);
1337 out_row = (uint16 *)_TIFFmalloc( out_size );
1339 for (y = 0; y < im->ysize; ++y) {
1340 if (i_gsamp_bits(im, 0, im->xsize, y, in_row, NULL, im->channels, 16) <= 0) {
1341 i_push_error(0, "Cannot read 16-bit samples");
1344 for (sample_index = 0; sample_index < sample_count; ++sample_index)
1345 out_row[sample_index] = in_row[sample_index];
1346 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1349 i_push_error(0, "write TIFF: write scan line failed");
1361 write_one_8(TIFF *tif, i_img *im) {
1362 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1364 unsigned char *out_row;
1366 size_t sample_count = im->xsize * im->channels;
1368 mm_log((1, "tiff - write_one_8(tif %p, im %p)\n", tif, im));
1370 if (!set_direct_tags(tif, im, compress, 8))
1373 out_size = TIFFScanlineSize(tif);
1374 if (out_size < sample_count)
1375 out_size = sample_count;
1376 out_row = (unsigned char *)_TIFFmalloc( out_size );
1378 for (y = 0; y < im->ysize; ++y) {
1379 if (i_gsamp(im, 0, im->xsize, y, out_row, NULL, im->channels) <= 0) {
1380 i_push_error(0, "Cannot read 8-bit samples");
1383 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1385 i_push_error(0, "write TIFF: write scan line failed");
1395 i_writetiff_low(TIFF *tif, i_img *im) {
1396 uint32 width, height;
1402 channels = im->channels;
1404 if (width != im->xsize || height != im->ysize) {
1405 i_push_error(0, "image too large for TIFF");
1409 mm_log((1, "i_writetiff_low: width=%d, height=%d, channels=%d, bits=%d\n", width, height, channels, im->bits));
1410 if (im->type == i_palette_type) {
1411 mm_log((1, "i_writetiff_low: paletted, colors=%d\n", i_colorcount(im)));
1414 if (i_img_is_monochrome(im, &zero_is_white)) {
1415 if (!write_one_bilevel(tif, im, zero_is_white))
1418 else if (im->type == i_palette_type) {
1419 if (i_colorcount(im) <= 16) {
1420 if (!write_one_paletted4(tif, im))
1424 if (!write_one_paletted8(tif, im))
1428 else if (im->bits > 16) {
1429 if (!write_one_32(tif, im))
1432 else if (im->bits > 8) {
1433 if (!write_one_16(tif, im))
1437 if (!write_one_8(tif, im))
1441 if (!save_tiff_tags(tif, im))
1448 =item i_writetiff_multi_wiol(ig, imgs, count, fine_mode)
1450 Stores an image in the iolayer object.
1452 ig - io_object that defines source to write to
1453 imgs,count - the images to write
1459 i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
1461 TIFFErrorHandler old_handler;
1463 tiffio_context_t ctx;
1465 i_mutex_lock(mutex);
1467 old_handler = TIFFSetErrorHandler(error_handler);
1470 mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n",
1473 tiffio_context_init(&ctx, ig);
1475 tif = TIFFClientOpen("No name",
1489 mm_log((1, "i_writetiff_multi_wiol: Unable to open tif file for writing\n"));
1490 i_push_error(0, "Could not create TIFF object");
1491 TIFFSetErrorHandler(old_handler);
1492 tiffio_context_final(&ctx);
1493 i_mutex_unlock(mutex);
1497 for (i = 0; i < count; ++i) {
1498 if (!i_writetiff_low(tif, imgs[i])) {
1500 TIFFSetErrorHandler(old_handler);
1501 tiffio_context_final(&ctx);
1502 i_mutex_unlock(mutex);
1506 if (!TIFFWriteDirectory(tif)) {
1507 i_push_error(0, "Cannot write TIFF directory");
1509 TIFFSetErrorHandler(old_handler);
1510 tiffio_context_final(&ctx);
1511 i_mutex_unlock(mutex);
1516 TIFFSetErrorHandler(old_handler);
1517 (void) TIFFClose(tif);
1518 tiffio_context_final(&ctx);
1520 i_mutex_unlock(mutex);
1529 =item i_writetiff_multi_wiol_faxable(ig, imgs, count, fine_mode)
1531 Stores an image in the iolayer object.
1533 ig - io_object that defines source to write to
1534 imgs,count - the images to write
1535 fine_mode - select fine or normal mode fax images
1542 i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
1545 TIFFErrorHandler old_handler;
1546 tiffio_context_t ctx;
1548 i_mutex_lock(mutex);
1550 old_handler = TIFFSetErrorHandler(error_handler);
1553 mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n",
1556 tiffio_context_init(&ctx, ig);
1558 tif = TIFFClientOpen("No name",
1572 mm_log((1, "i_writetiff_mulit_wiol: Unable to open tif file for writing\n"));
1573 i_push_error(0, "Could not create TIFF object");
1574 TIFFSetErrorHandler(old_handler);
1575 tiffio_context_final(&ctx);
1576 i_mutex_unlock(mutex);
1580 for (i = 0; i < count; ++i) {
1581 if (!i_writetiff_low_faxable(tif, imgs[i], fine)) {
1583 TIFFSetErrorHandler(old_handler);
1584 tiffio_context_final(&ctx);
1585 i_mutex_unlock(mutex);
1589 if (!TIFFWriteDirectory(tif)) {
1590 i_push_error(0, "Cannot write TIFF directory");
1592 TIFFSetErrorHandler(old_handler);
1593 tiffio_context_final(&ctx);
1594 i_mutex_unlock(mutex);
1599 (void) TIFFClose(tif);
1600 TIFFSetErrorHandler(old_handler);
1601 tiffio_context_final(&ctx);
1603 i_mutex_unlock(mutex);
1612 =item i_writetiff_wiol(im, ig)
1614 Stores an image in the iolayer object.
1616 im - image object to write out
1617 ig - io_object that defines source to write to
1622 i_writetiff_wiol(i_img *img, io_glue *ig) {
1624 TIFFErrorHandler old_handler;
1625 tiffio_context_t ctx;
1627 i_mutex_lock(mutex);
1629 old_handler = TIFFSetErrorHandler(error_handler);
1632 mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", img, ig));
1634 tiffio_context_init(&ctx, ig);
1636 tif = TIFFClientOpen("No name",
1650 mm_log((1, "i_writetiff_wiol: Unable to open tif file for writing\n"));
1651 i_push_error(0, "Could not create TIFF object");
1652 tiffio_context_final(&ctx);
1653 TIFFSetErrorHandler(old_handler);
1654 i_mutex_unlock(mutex);
1658 if (!i_writetiff_low(tif, img)) {
1660 tiffio_context_final(&ctx);
1661 TIFFSetErrorHandler(old_handler);
1662 i_mutex_unlock(mutex);
1666 (void) TIFFClose(tif);
1667 TIFFSetErrorHandler(old_handler);
1668 tiffio_context_final(&ctx);
1669 i_mutex_unlock(mutex);
1680 =item i_writetiff_wiol_faxable(i_img *, io_glue *)
1682 Stores an image in the iolayer object in faxable tiff format.
1684 im - image object to write out
1685 ig - io_object that defines source to write to
1687 Note, this may be rewritten to use to simply be a call to a
1688 lower-level function that gives more options for writing tiff at some
1695 i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine) {
1697 TIFFErrorHandler old_handler;
1698 tiffio_context_t ctx;
1700 i_mutex_lock(mutex);
1702 old_handler = TIFFSetErrorHandler(error_handler);
1705 mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", im, ig));
1707 tiffio_context_init(&ctx, ig);
1709 tif = TIFFClientOpen("No name",
1723 mm_log((1, "i_writetiff_wiol: Unable to open tif file for writing\n"));
1724 i_push_error(0, "Could not create TIFF object");
1725 TIFFSetErrorHandler(old_handler);
1726 tiffio_context_final(&ctx);
1727 i_mutex_unlock(mutex);
1731 if (!i_writetiff_low_faxable(tif, im, fine)) {
1733 TIFFSetErrorHandler(old_handler);
1734 tiffio_context_final(&ctx);
1735 i_mutex_unlock(mutex);
1739 (void) TIFFClose(tif);
1740 TIFFSetErrorHandler(old_handler);
1741 tiffio_context_final(&ctx);
1742 i_mutex_unlock(mutex);
1750 static int save_tiff_tags(TIFF *tif, i_img *im) {
1753 for (i = 0; i < text_tag_count; ++i) {
1755 if (i_tags_find(&im->tags, text_tag_names[i].name, 0, &entry)) {
1756 if (!TIFFSetField(tif, text_tag_names[i].tag,
1757 im->tags.tags[entry].data)) {
1758 i_push_errorf(0, "cannot save %s to TIFF", text_tag_names[i].name);
1769 unpack_4bit_to(unsigned char *dest, const unsigned char *src,
1770 size_t src_byte_count) {
1771 while (src_byte_count > 0) {
1772 *dest++ = *src >> 4;
1773 *dest++ = *src++ & 0xf;
1778 static void pack_4bit_to(unsigned char *dest, const unsigned char *src,
1779 i_img_dim pixel_count) {
1781 while (i < pixel_count) {
1783 *dest = *src++ << 4;
1793 =item fallback_rgb_channels
1795 Calculate the number of output channels when we fallback to the RGBA
1796 family of functions.
1802 fallback_rgb_channels(TIFF *tif, i_img_dim width, i_img_dim height, int *channels, int *alpha_chan) {
1808 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &in_channels);
1809 TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
1811 switch (photometric) {
1812 case PHOTOMETRIC_SEPARATED:
1816 case PHOTOMETRIC_MINISWHITE:
1817 case PHOTOMETRIC_MINISBLACK:
1818 /* the TIFF RGBA functions expand single channel grey into RGB,
1819 so reduce it, we move the alpha channel into the right place
1828 /* TIFF images can have more than one alpha channel, but Imager can't
1829 this ignores the possibility of 2 channel images with 2 alpha,
1830 but there's not much I can do about that */
1832 if (TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)
1834 *alpha_chan = (*channels)++;
1839 make_rgb(TIFF *tif, i_img_dim width, i_img_dim height, int *alpha_chan) {
1842 fallback_rgb_channels(tif, width, height, &channels, alpha_chan);
1844 return i_img_8_new(width, height, channels);
1848 read_one_rgb_lines(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete) {
1850 uint32* raster = NULL;
1851 uint32 rowsperstrip, row;
1856 im = make_rgb(tif, width, height, &alpha_chan);
1860 rc = TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1861 mm_log((1, "i_readtiff_wiol: rowsperstrip=%d rc = %d\n", rowsperstrip, rc));
1863 if (rc != 1 || rowsperstrip==-1) {
1864 rowsperstrip = height;
1867 raster = (uint32*)_TIFFmalloc(width * rowsperstrip * sizeof (uint32));
1870 i_push_error(0, "No space for raster buffer");
1874 line_buf = mymalloc(sizeof(i_color) * width);
1876 for( row = 0; row < height; row += rowsperstrip ) {
1877 uint32 newrows, i_row;
1879 if (!TIFFReadRGBAStrip(tif, row, raster)) {
1880 if (allow_incomplete) {
1881 i_tags_setn(&im->tags, "i_lines_read", row);
1882 i_tags_setn(&im->tags, "i_incomplete", 1);
1886 i_push_error(0, "could not read TIFF image strip");
1893 newrows = (row+rowsperstrip > height) ? height-row : rowsperstrip;
1894 mm_log((1, "newrows=%d\n", newrows));
1896 for( i_row = 0; i_row < newrows; i_row++ ) {
1898 i_color *outp = line_buf;
1900 for(x = 0; x<width; x++) {
1901 uint32 temp = raster[x+width*(newrows-i_row-1)];
1902 outp->rgba.r = TIFFGetR(temp);
1903 outp->rgba.g = TIFFGetG(temp);
1904 outp->rgba.b = TIFFGetB(temp);
1907 /* the libtiff RGBA code expands greyscale into RGBA, so put the
1908 alpha in the right place and scale it */
1910 outp->channel[alpha_chan] = TIFFGetA(temp);
1911 if (outp->channel[alpha_chan]) {
1912 for (ch = 0; ch < alpha_chan; ++ch) {
1913 outp->channel[ch] = outp->channel[ch] * 255 / outp->channel[alpha_chan];
1920 i_plin(im, 0, width, i_row+row, line_buf);
1930 /* adapted from libtiff
1932 libtiff's TIFFReadRGBATile succeeds even when asked to read an
1933 invalid tile, which means we have no way of knowing whether the data
1934 we received from it is valid or not.
1936 So the caller here has set stoponerror to 1 so that
1937 TIFFRGBAImageGet() will fail.
1939 read_one_rgb_tiled() then takes that into account for i_incomplete
1943 myTIFFReadRGBATile(TIFFRGBAImage *img, uint32 col, uint32 row, uint32 * raster)
1947 uint32 tile_xsize, tile_ysize;
1948 uint32 read_xsize, read_ysize;
1952 * Verify that our request is legal - on a tile file, and on a
1956 TIFFGetFieldDefaulted(img->tif, TIFFTAG_TILEWIDTH, &tile_xsize);
1957 TIFFGetFieldDefaulted(img->tif, TIFFTAG_TILELENGTH, &tile_ysize);
1958 if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 )
1960 i_push_errorf(0, "Row/col passed to myTIFFReadRGBATile() must be top"
1961 "left corner of a tile.");
1966 * The TIFFRGBAImageGet() function doesn't allow us to get off the
1967 * edge of the image, even to fill an otherwise valid tile. So we
1968 * figure out how much we can read, and fix up the tile buffer to
1969 * a full tile configuration afterwards.
1972 if( row + tile_ysize > img->height )
1973 read_ysize = img->height - row;
1975 read_ysize = tile_ysize;
1977 if( col + tile_xsize > img->width )
1978 read_xsize = img->width - col;
1980 read_xsize = tile_xsize;
1983 * Read the chunk of imagery.
1986 img->row_offset = row;
1987 img->col_offset = col;
1989 ok = TIFFRGBAImageGet(img, raster, read_xsize, read_ysize );
1992 * If our read was incomplete we will need to fix up the tile by
1993 * shifting the data around as if a full tile of data is being returned.
1995 * This is all the more complicated because the image is organized in
1996 * bottom to top format.
1999 if( read_xsize == tile_xsize && read_ysize == tile_ysize )
2002 for( i_row = 0; i_row < read_ysize; i_row++ ) {
2003 memmove( raster + (tile_ysize - i_row - 1) * tile_xsize,
2004 raster + (read_ysize - i_row - 1) * read_xsize,
2005 read_xsize * sizeof(uint32) );
2006 _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize,
2007 0, sizeof(uint32) * (tile_xsize - read_xsize) );
2010 for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) {
2011 _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize,
2012 0, sizeof(uint32) * tile_xsize );
2019 read_one_rgb_tiled(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete) {
2021 uint32* raster = NULL;
2024 uint32 tile_width, tile_height;
2025 unsigned long pixels = 0;
2026 char emsg[1024] = "";
2031 im = make_rgb(tif, width, height, &alpha_chan);
2035 if (!TIFFRGBAImageOK(tif, emsg)
2036 || !TIFFRGBAImageBegin(&img, tif, 1, emsg)) {
2037 i_push_error(0, emsg);
2042 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width);
2043 TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height);
2044 mm_log((1, "i_readtiff_wiol: tile_width=%d, tile_height=%d\n", tile_width, tile_height));
2046 raster = (uint32*)_TIFFmalloc(tile_width * tile_height * sizeof (uint32));
2049 i_push_error(0, "No space for raster buffer");
2050 TIFFRGBAImageEnd(&img);
2053 line = mymalloc(tile_width * sizeof(i_color));
2055 for( row = 0; row < height; row += tile_height ) {
2056 for( col = 0; col < width; col += tile_width ) {
2058 /* Read the tile into an RGBA array */
2059 if (myTIFFReadRGBATile(&img, col, row, raster)) {
2061 uint32 newrows = (row+tile_height > height) ? height-row : tile_height;
2062 uint32 newcols = (col+tile_width > width ) ? width-col : tile_width;
2064 mm_log((1, "i_readtiff_wiol: tile(%d, %d) newcols=%d newrows=%d\n", col, row, newcols, newrows));
2065 for( i_row = 0; i_row < newrows; i_row++ ) {
2066 i_color *outp = line;
2067 for(x = 0; x < newcols; x++) {
2068 uint32 temp = raster[x+tile_width*(tile_height-i_row-1)];
2069 outp->rgba.r = TIFFGetR(temp);
2070 outp->rgba.g = TIFFGetG(temp);
2071 outp->rgba.b = TIFFGetB(temp);
2072 outp->rgba.a = TIFFGetA(temp);
2075 /* the libtiff RGBA code expands greyscale into RGBA, so put the
2076 alpha in the right place and scale it */
2078 outp->channel[alpha_chan] = TIFFGetA(temp);
2080 if (outp->channel[alpha_chan]) {
2081 for (ch = 0; ch < alpha_chan; ++ch) {
2082 outp->channel[ch] = outp->channel[ch] * 255 / outp->channel[alpha_chan];
2089 i_plin(im, col, col+newcols, row+i_row, line);
2091 pixels += newrows * newcols;
2094 if (allow_incomplete) {
2106 i_push_error(0, "TIFF: No image data could be read from the image");
2110 /* incomplete image */
2111 i_tags_setn(&im->tags, "i_incomplete", 1);
2112 i_tags_setn(&im->tags, "i_lines_read", pixels / width);
2116 TIFFRGBAImageEnd(&img);
2124 TIFFRGBAImageEnd(&img);
2130 i_tiff_libversion(void) {
2131 return TIFFGetVersion();
2135 setup_paletted(read_state_t *state) {
2138 int color_count = 1 << state->bits_per_sample;
2140 state->img = i_img_pal_new(state->width, state->height, 3, 256);
2144 /* setup the color map */
2145 if (!TIFFGetField(state->tif, TIFFTAG_COLORMAP, maps+0, maps+1, maps+2)) {
2146 i_push_error(0, "Cannot get colormap for paletted image");
2147 i_img_destroy(state->img);
2150 for (i = 0; i < color_count; ++i) {
2152 for (ch = 0; ch < 3; ++ch) {
2153 c.channel[ch] = Sample16To8(maps[ch][i]);
2155 i_addcolors(state->img, &c, 1);
2162 tile_contig_getter(read_state_t *state, read_putter_t putter) {
2163 uint32 tile_width, tile_height;
2164 uint32 this_tile_height, this_tile_width;
2165 uint32 rows_left, cols_left;
2168 state->raster = _TIFFmalloc(TIFFTileSize(state->tif));
2169 if (!state->raster) {
2170 i_push_error(0, "tiff: Out of memory allocating tile buffer");
2174 TIFFGetField(state->tif, TIFFTAG_TILEWIDTH, &tile_width);
2175 TIFFGetField(state->tif, TIFFTAG_TILELENGTH, &tile_height);
2176 rows_left = state->height;
2177 for (y = 0; y < state->height; y += this_tile_height) {
2178 this_tile_height = rows_left > tile_height ? tile_height : rows_left;
2180 cols_left = state->width;
2181 for (x = 0; x < state->width; x += this_tile_width) {
2182 this_tile_width = cols_left > tile_width ? tile_width : cols_left;
2184 if (TIFFReadTile(state->tif,
2187 if (!state->allow_incomplete) {
2192 putter(state, x, y, this_tile_width, this_tile_height, tile_width - this_tile_width);
2195 cols_left -= this_tile_width;
2198 rows_left -= this_tile_height;
2205 strip_contig_getter(read_state_t *state, read_putter_t putter) {
2206 uint32 rows_per_strip;
2207 tsize_t strip_size = TIFFStripSize(state->tif);
2208 uint32 y, strip_rows, rows_left;
2210 state->raster = _TIFFmalloc(strip_size);
2211 if (!state->raster) {
2212 i_push_error(0, "tiff: Out of memory allocating strip buffer");
2216 TIFFGetFieldDefaulted(state->tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
2217 rows_left = state->height;
2218 for (y = 0; y < state->height; y += strip_rows) {
2219 strip_rows = rows_left > rows_per_strip ? rows_per_strip : rows_left;
2220 if (TIFFReadEncodedStrip(state->tif,
2221 TIFFComputeStrip(state->tif, y, 0),
2224 if (!state->allow_incomplete)
2228 putter(state, 0, y, state->width, strip_rows, 0);
2230 rows_left -= strip_rows;
2237 paletted_putter8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, int extras) {
2238 unsigned char *p = state->raster;
2240 state->pixels_read += width * height;
2241 while (height > 0) {
2242 i_ppal(state->img, x, x + width, y, p);
2243 p += width + extras;
2252 paletted_putter4(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, int extras) {
2253 uint32 img_line_size = (width + 1) / 2;
2254 uint32 skip_line_size = (width + extras + 1) / 2;
2255 unsigned char *p = state->raster;
2257 if (!state->line_buf)
2258 state->line_buf = mymalloc(state->width);
2260 state->pixels_read += width * height;
2261 while (height > 0) {
2262 unpack_4bit_to(state->line_buf, p, img_line_size);
2263 i_ppal(state->img, x, x + width, y, state->line_buf);
2264 p += skip_line_size;
2273 rgb_channels(read_state_t *state, int *out_channels) {
2279 state->alpha_chan = 0;
2280 state->scale_alpha = 0;
2283 if (state->samples_per_pixel == 3)
2286 if (!TIFFGetField(state->tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)) {
2287 mm_log((1, "tiff: samples != 3 but no extra samples tag\n"));
2292 mm_log((1, "tiff: samples != 3 but no extra samples listed"));
2297 state->alpha_chan = 3;
2299 case EXTRASAMPLE_UNSPECIFIED:
2300 case EXTRASAMPLE_ASSOCALPHA:
2301 state->scale_alpha = 1;
2304 case EXTRASAMPLE_UNASSALPHA:
2305 state->scale_alpha = 0;
2309 mm_log((1, "tiff: unknown extra sample type %d, treating as assoc alpha\n",
2311 state->scale_alpha = 1;
2314 mm_log((1, "tiff alpha channel %d scale %d\n", state->alpha_chan, state->scale_alpha));
2318 grey_channels(read_state_t *state, int *out_channels) {
2324 state->alpha_chan = 0;
2325 state->scale_alpha = 0;
2328 if (state->samples_per_pixel == 1)
2331 if (!TIFFGetField(state->tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)) {
2332 mm_log((1, "tiff: samples != 1 but no extra samples tag\n"));
2337 mm_log((1, "tiff: samples != 1 but no extra samples listed"));
2342 state->alpha_chan = 1;
2344 case EXTRASAMPLE_UNSPECIFIED:
2345 case EXTRASAMPLE_ASSOCALPHA:
2346 state->scale_alpha = 1;
2349 case EXTRASAMPLE_UNASSALPHA:
2350 state->scale_alpha = 0;
2354 mm_log((1, "tiff: unknown extra sample type %d, treating as assoc alpha\n",
2356 state->scale_alpha = 1;
2362 setup_16_rgb(read_state_t *state) {
2365 rgb_channels(state, &out_channels);
2367 state->img = i_img_16_new(state->width, state->height, out_channels);
2370 state->line_buf = mymalloc(sizeof(unsigned) * state->width * out_channels);
2376 setup_16_grey(read_state_t *state) {
2379 grey_channels(state, &out_channels);
2381 state->img = i_img_16_new(state->width, state->height, out_channels);
2384 state->line_buf = mymalloc(sizeof(unsigned) * state->width * out_channels);
2390 putter_16(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
2392 uint16 *p = state->raster;
2393 int out_chan = state->img->channels;
2395 state->pixels_read += width * height;
2396 while (height > 0) {
2399 unsigned *outp = state->line_buf;
2401 for (i = 0; i < width; ++i) {
2402 for (ch = 0; ch < out_chan; ++ch) {
2405 if (state->alpha_chan && state->scale_alpha && outp[state->alpha_chan]) {
2406 for (ch = 0; ch < state->alpha_chan; ++ch) {
2407 int result = 0.5 + (outp[ch] * 65535.0 / outp[state->alpha_chan]);
2408 outp[ch] = CLAMP16(result);
2411 p += state->samples_per_pixel;
2415 i_psamp_bits(state->img, x, x + width, y, state->line_buf, NULL, out_chan, 16);
2417 p += row_extras * state->samples_per_pixel;
2426 setup_8_rgb(read_state_t *state) {
2429 rgb_channels(state, &out_channels);
2431 state->img = i_img_8_new(state->width, state->height, out_channels);
2434 state->line_buf = mymalloc(sizeof(unsigned) * state->width * out_channels);
2440 setup_8_grey(read_state_t *state) {
2443 grey_channels(state, &out_channels);
2445 state->img = i_img_8_new(state->width, state->height, out_channels);
2448 state->line_buf = mymalloc(sizeof(i_color) * state->width * out_channels);
2454 putter_8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
2456 unsigned char *p = state->raster;
2457 int out_chan = state->img->channels;
2459 state->pixels_read += width * height;
2460 while (height > 0) {
2463 i_color *outp = state->line_buf;
2465 for (i = 0; i < width; ++i) {
2466 for (ch = 0; ch < out_chan; ++ch) {
2467 outp->channel[ch] = p[ch];
2469 if (state->alpha_chan && state->scale_alpha
2470 && outp->channel[state->alpha_chan]) {
2471 for (ch = 0; ch < state->alpha_chan; ++ch) {
2472 int result = (outp->channel[ch] * 255 + 127) / outp->channel[state->alpha_chan];
2474 outp->channel[ch] = CLAMP8(result);
2477 p += state->samples_per_pixel;
2481 i_plin(state->img, x, x + width, y, state->line_buf);
2483 p += row_extras * state->samples_per_pixel;
2492 setup_32_rgb(read_state_t *state) {
2495 rgb_channels(state, &out_channels);
2497 state->img = i_img_double_new(state->width, state->height, out_channels);
2500 state->line_buf = mymalloc(sizeof(i_fcolor) * state->width);
2506 setup_32_grey(read_state_t *state) {
2509 grey_channels(state, &out_channels);
2511 state->img = i_img_double_new(state->width, state->height, out_channels);
2514 state->line_buf = mymalloc(sizeof(i_fcolor) * state->width);
2520 putter_32(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
2522 uint32 *p = state->raster;
2523 int out_chan = state->img->channels;
2525 state->pixels_read += width * height;
2526 while (height > 0) {
2529 i_fcolor *outp = state->line_buf;
2531 for (i = 0; i < width; ++i) {
2532 for (ch = 0; ch < out_chan; ++ch) {
2533 outp->channel[ch] = p[ch] / 4294967295.0;
2535 if (state->alpha_chan && state->scale_alpha && outp->channel[state->alpha_chan]) {
2536 for (ch = 0; ch < state->alpha_chan; ++ch)
2537 outp->channel[ch] /= outp->channel[state->alpha_chan];
2539 p += state->samples_per_pixel;
2543 i_plinf(state->img, x, x + width, y, state->line_buf);
2545 p += row_extras * state->samples_per_pixel;
2554 setup_bilevel(read_state_t *state) {
2555 i_color black, white;
2556 state->img = i_img_pal_new(state->width, state->height, 1, 256);
2559 black.channel[0] = black.channel[1] = black.channel[2] =
2560 black.channel[3] = 0;
2561 white.channel[0] = white.channel[1] = white.channel[2] =
2562 white.channel[3] = 255;
2563 if (state->photometric == PHOTOMETRIC_MINISBLACK) {
2564 i_addcolors(state->img, &black, 1);
2565 i_addcolors(state->img, &white, 1);
2568 i_addcolors(state->img, &white, 1);
2569 i_addcolors(state->img, &black, 1);
2571 state->line_buf = mymalloc(state->width);
2577 putter_bilevel(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
2579 unsigned char *line_in = state->raster;
2580 size_t line_size = (width + row_extras + 7) / 8;
2582 /* tifflib returns the bits in MSB2LSB order even when the file is
2583 in LSB2MSB, so we only need to handle MSB2LSB */
2584 state->pixels_read += width * height;
2585 while (height > 0) {
2587 unsigned char *outp = state->line_buf;
2588 unsigned char *inp = line_in;
2589 unsigned mask = 0x80;
2591 for (i = 0; i < width; ++i) {
2592 *outp++ = *inp & mask ? 1 : 0;
2600 i_ppal(state->img, x, x + width, y, state->line_buf);
2602 line_in += line_size;
2611 cmyk_channels(read_state_t *state, int *out_channels) {
2617 state->alpha_chan = 0;
2618 state->scale_alpha = 0;
2621 if (state->samples_per_pixel == 4)
2624 if (!TIFFGetField(state->tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)) {
2625 mm_log((1, "tiff: CMYK samples != 4 but no extra samples tag\n"));
2630 mm_log((1, "tiff: CMYK samples != 4 but no extra samples listed"));
2635 state->alpha_chan = 4;
2637 case EXTRASAMPLE_UNSPECIFIED:
2638 case EXTRASAMPLE_ASSOCALPHA:
2639 state->scale_alpha = 1;
2642 case EXTRASAMPLE_UNASSALPHA:
2643 state->scale_alpha = 0;
2647 mm_log((1, "tiff: unknown extra sample type %d, treating as assoc alpha\n",
2649 state->scale_alpha = 1;
2655 setup_cmyk8(read_state_t *state) {
2658 cmyk_channels(state, &channels);
2659 state->img = i_img_8_new(state->width, state->height, channels);
2661 state->line_buf = mymalloc(sizeof(i_color) * state->width);
2667 putter_cmyk8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
2669 unsigned char *p = state->raster;
2671 state->pixels_read += width * height;
2672 while (height > 0) {
2675 i_color *outp = state->line_buf;
2677 for (i = 0; i < width; ++i) {
2678 unsigned char c, m, y, k;
2683 outp->rgba.r = (k * (255 - c)) / 255;
2684 outp->rgba.g = (k * (255 - m)) / 255;
2685 outp->rgba.b = (k * (255 - y)) / 255;
2686 if (state->alpha_chan) {
2687 outp->rgba.a = p[state->alpha_chan];
2688 if (state->scale_alpha
2690 for (ch = 0; ch < 3; ++ch) {
2691 int result = (outp->channel[ch] * 255 + 127) / outp->rgba.a;
2692 outp->channel[ch] = CLAMP8(result);
2696 p += state->samples_per_pixel;
2700 i_plin(state->img, x, x + width, y, state->line_buf);
2702 p += row_extras * state->samples_per_pixel;
2711 setup_cmyk16(read_state_t *state) {
2714 cmyk_channels(state, &channels);
2715 state->img = i_img_16_new(state->width, state->height, channels);
2717 state->line_buf = mymalloc(sizeof(unsigned) * state->width * channels);
2723 putter_cmyk16(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
2725 uint16 *p = state->raster;
2726 int out_chan = state->img->channels;
2728 mm_log((4, "putter_cmyk16(%p, %d, %d, %d, %d, %d)\n", x, y, width, height, row_extras));
2730 state->pixels_read += width * height;
2731 while (height > 0) {
2734 unsigned *outp = state->line_buf;
2736 for (i = 0; i < width; ++i) {
2737 unsigned c, m, y, k;
2742 outp[0] = (k * (65535U - c)) / 65535U;
2743 outp[1] = (k * (65535U - m)) / 65535U;
2744 outp[2] = (k * (65535U - y)) / 65535U;
2745 if (state->alpha_chan) {
2746 outp[3] = p[state->alpha_chan];
2747 if (state->scale_alpha
2749 for (ch = 0; ch < 3; ++ch) {
2750 int result = (outp[ch] * 65535 + 32767) / outp[3];
2751 outp[3] = CLAMP16(result);
2755 p += state->samples_per_pixel;
2759 i_psamp_bits(state->img, x, x + width, y, state->line_buf, NULL, out_chan, 16);
2761 p += row_extras * state->samples_per_pixel;
2771 Older versions of tifflib we support don't define this, so define it
2774 If you want this detection to do anything useful, use a newer
2778 #if TIFFLIB_VERSION < 20031121
2781 TIFFIsCODECConfigured(uint16 scheme) {
2783 /* these schemes are all shipped with tifflib */
2784 case COMPRESSION_NONE:
2785 case COMPRESSION_PACKBITS:
2786 case COMPRESSION_CCITTRLE:
2787 case COMPRESSION_CCITTRLEW:
2788 case COMPRESSION_CCITTFAX3:
2789 case COMPRESSION_CCITTFAX4:
2792 /* these require external library support */
2794 case COMPRESSION_JPEG:
2795 case COMPRESSION_LZW:
2796 case COMPRESSION_DEFLATE:
2797 case COMPRESSION_ADOBE_DEFLATE:
2805 myTIFFIsCODECConfigured(uint16 scheme) {
2806 #if TIFFLIB_VERSION < 20040724
2807 if (scheme == COMPRESSION_LZW)
2811 return TIFFIsCODECConfigured(scheme);
2815 tiffio_context_init(tiffio_context_t *c, io_glue *ig) {
2816 c->magic = TIFFIO_MAGIC;
2818 #ifdef USE_EXT_WARN_HANDLER
2819 c->warn_buffer = NULL;
2825 tiffio_context_final(tiffio_context_t *c) {
2826 c->magic = TIFFIO_MAGIC;
2827 #ifdef USE_EXT_WARN_HANDLER
2829 myfree(c->warn_buffer);
2838 Arnar M. Hrafnkelsson <addi@umich.edu>, Tony Cook <tonyc@cpan.org>