[rt #74540] handle the TIFF SampleFormat tag
[imager.git] / TIFF / imtiff.c
CommitLineData
bd8052a6 1#include <tiffio.h>
e5ee047b
TC
2#include <string.h>
3#include "imtiff.h"
4#include "imext.h"
5c829fcf 5
bd8052a6
TC
6/* needed to implement our substitute TIFFIsCODECConfigured */
7#if TIFFLIB_VERSION < 20031121
bd8052a6
TC
8static int TIFFIsCODECConfigured(uint16 scheme);
9#endif
10
02d1d628
AMH
11/*
12=head1 NAME
13
14tiff.c - implements reading and writing tiff files, uses io layer.
15
16=head1 SYNOPSIS
17
18 io_glue *ig = io_new_fd( fd );
19 i_img *im = i_readtiff_wiol(ig, -1); // no limit on how much is read
20 // or
21 io_glue *ig = io_new_fd( fd );
22 return_code = i_writetiff_wiol(im, ig);
23
24=head1 DESCRIPTION
25
26tiff.c implements the basic functions to read and write tiff files.
27It uses the iolayer and needs either a seekable source or an entire
28memory mapped buffer.
29
30=head1 FUNCTION REFERENCE
31
32Some of these functions are internal.
33
b8c2033e 34=over
02d1d628
AMH
35
36=cut
37*/
38
5c829fcf
AMH
39#define byteswap_macro(x) \
40 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
41 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
42
bd8052a6
TC
43#define CLAMP8(x) ((x) < 0 ? 0 : (x) > 255 ? 255 : (x))
44#define CLAMP16(x) ((x) < 0 ? 0 : (x) > 65535 ? 65535 : (x))
45
e5ee047b
TC
46#define Sample16To8(num) ((num) / 257)
47
fd9a31d2
TC
48struct tag_name {
49 char *name;
50 uint32 tag;
51};
52
8d14daab
TC
53static i_img *read_one_rgb_tiled(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete);
54static i_img *read_one_rgb_lines(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete);
bd8052a6 55
fd9a31d2
TC
56static struct tag_name text_tag_names[] =
57{
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, },
67};
68
bd8052a6
TC
69static struct tag_name
70compress_values[] =
71 {
72 { "none", COMPRESSION_NONE },
73 { "ccittrle", COMPRESSION_CCITTRLE },
74 { "fax3", COMPRESSION_CCITTFAX3 },
b57dd0e4 75 { "t4", COMPRESSION_CCITTFAX3 },
bd8052a6 76 { "fax4", COMPRESSION_CCITTFAX4 },
b57dd0e4 77 { "t6", COMPRESSION_CCITTFAX4 },
bd8052a6
TC
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 },
85 };
86
87static const int compress_value_count =
88 sizeof(compress_values) / sizeof(*compress_values);
89
05c9b356
TC
90static struct tag_name
91sample_format_values[] =
92 {
93 "uint", SAMPLEFORMAT_UINT,
94 "int", SAMPLEFORMAT_INT,
95 "ieeefp", SAMPLEFORMAT_IEEEFP,
96 "undefined", SAMPLEFORMAT_VOID,
97 };
98
99static const int sample_format_value_count =
100 sizeof(sample_format_values) / sizeof(*sample_format_values);
101
f8d72f20
TC
102static int
103myTIFFIsCODECConfigured(uint16 scheme);
104
bd8052a6
TC
105typedef struct read_state_tag read_state_t;
106/* the setup function creates the image object, allocates the line buffer */
107typedef int (*read_setup_t)(read_state_t *state);
108
109/* the putter writes the image data provided by the getter to the
110 image, x, y, width, height describe the target area of the image,
111 extras is the extra number of pixels stored for each scanline in
112 the raster buffer, (for tiles against the right side of the
113 image) */
114
8d14daab
TC
115typedef int (*read_putter_t)(read_state_t *state, i_img_dim x, i_img_dim y,
116 i_img_dim width, i_img_dim height, int extras);
bd8052a6
TC
117
118/* reads from a tiled or strip image and calls the putter.
119 This may need a second type for handling non-contiguous images
120 at some point */
121typedef int (*read_getter_t)(read_state_t *state, read_putter_t putter);
122
123struct read_state_tag {
124 TIFF *tif;
125 i_img *img;
126 void *raster;
8d14daab 127 i_img_dim pixels_read;
bd8052a6
TC
128 int allow_incomplete;
129 void *line_buf;
130 uint32 width, height;
131 uint16 bits_per_sample;
132 uint16 photometric;
133
134 /* the total number of channels (samples per pixel) */
135 int samples_per_pixel;
136
137 /* if non-zero, which channel is the alpha channel, typically 3 for rgb */
138 int alpha_chan;
139
140 /* whether or not to scale the color channels based on the alpha
141 channel. TIFF has 2 types of alpha channel, if the alpha channel
142 we use is EXTRASAMPLE_ASSOCALPHA then the color data will need to
143 be scaled to match Imager's conventions */
144 int scale_alpha;
05c9b356
TC
145
146 /* number of color samples (not including alpha) */
147 int color_channels;
148
149 /* SampleFormat is 2 */
150 int sample_signed;
151
152 int sample_format;
bd8052a6
TC
153};
154
155static int tile_contig_getter(read_state_t *state, read_putter_t putter);
156static int strip_contig_getter(read_state_t *state, read_putter_t putter);
157
158static int setup_paletted(read_state_t *state);
8d14daab
TC
159static int paletted_putter8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
160static int paletted_putter4(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
bd8052a6
TC
161
162static int setup_16_rgb(read_state_t *state);
163static int setup_16_grey(read_state_t *state);
8d14daab 164static int putter_16(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
bd8052a6
TC
165
166static int setup_8_rgb(read_state_t *state);
167static int setup_8_grey(read_state_t *state);
8d14daab 168static int putter_8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
bd8052a6
TC
169
170static int setup_32_rgb(read_state_t *state);
171static int setup_32_grey(read_state_t *state);
8d14daab 172static int putter_32(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
bd8052a6
TC
173
174static int setup_bilevel(read_state_t *state);
8d14daab 175static int putter_bilevel(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
bd8052a6
TC
176
177static int setup_cmyk8(read_state_t *state);
8d14daab 178static int putter_cmyk8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
bd8052a6
TC
179
180static int setup_cmyk16(read_state_t *state);
8d14daab 181static int putter_cmyk16(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
6b7197d0
TC
182static void
183rgb_channels(read_state_t *state, int *out_channels);
184static void
185grey_channels(read_state_t *state, int *out_channels);
186static void
187cmyk_channels(read_state_t *state, int *out_channels);
188static void
189fallback_rgb_channels(TIFF *tif, i_img_dim width, i_img_dim height, int *channels, int *alpha_chan);
bd8052a6 190
fd9a31d2
TC
191static const int text_tag_count =
192 sizeof(text_tag_names) / sizeof(*text_tag_names);
5c829fcf 193
60715047
TC
194#if TIFFLIB_VERSION >= 20051230
195#define USE_EXT_WARN_HANDLER
196#endif
197
198#define TIFFIO_MAGIC 0xC6A340CC
199
5bb828f1 200static void error_handler(char const *module, char const *fmt, va_list ap) {
bd8052a6 201 mm_log((1, "tiff error fmt %s\n", fmt));
5bb828f1
TC
202 i_push_errorvf(0, fmt, ap);
203}
204
60715047
TC
205typedef struct {
206 unsigned magic;
207 io_glue *ig;
208#ifdef USE_EXT_WARN_HANDLER
209 char *warn_buffer;
210 size_t warn_size;
211#endif
212} tiffio_context_t;
213
214static void
215tiffio_context_init(tiffio_context_t *c, io_glue *ig);
216static void
217tiffio_context_final(tiffio_context_t *c);
218
ffeb4a67 219#define WARN_BUFFER_LIMIT 10000
60715047
TC
220
221#ifdef USE_EXT_WARN_HANDLER
222
223static void
224warn_handler_ex(thandle_t h, const char *module, const char *fmt, va_list ap) {
225 tiffio_context_t *c = (tiffio_context_t *)h;
226 char buf[200];
227
228 if (c->magic != TIFFIO_MAGIC)
229 return;
230
231 buf[0] = '\0';
232#ifdef IMAGER_VSNPRINTF
233 vsnprintf(buf, sizeof(buf), fmt, ap);
234#else
235 vsprintf(buf, fmt, ap);
236#endif
237 mm_log((1, "tiff warning %s\n", buf));
238
239 if (!c->warn_buffer || strlen(c->warn_buffer)+strlen(buf)+2 > c->warn_size) {
240 size_t new_size = c->warn_size + strlen(buf) + 2;
241 char *old_buffer = c->warn_buffer;
242 if (new_size > WARN_BUFFER_LIMIT) {
243 new_size = WARN_BUFFER_LIMIT;
244 }
245 c->warn_buffer = myrealloc(c->warn_buffer, new_size);
246 if (!old_buffer) c->warn_buffer[0] = '\0';
247 c->warn_size = new_size;
248 }
249 if (strlen(c->warn_buffer)+strlen(buf)+2 <= c->warn_size) {
250 strcat(c->warn_buffer, buf);
251 strcat(c->warn_buffer, "\n");
252 }
253}
254
255#else
256
ffeb4a67
TC
257static char *warn_buffer = NULL;
258static int warn_buffer_size = 0;
259
be371490 260static void warn_handler(char const *module, char const *fmt, va_list ap) {
ffeb4a67
TC
261 char buf[1000];
262
263 buf[0] = '\0';
86c8d19a 264#ifdef IMAGER_VSNPRINTF
ffeb4a67
TC
265 vsnprintf(buf, sizeof(buf), fmt, ap);
266#else
267 vsprintf(buf, fmt, ap);
268#endif
bd8052a6
TC
269 mm_log((1, "tiff warning %s\n", buf));
270
ffeb4a67
TC
271 if (!warn_buffer || strlen(warn_buffer)+strlen(buf)+2 > warn_buffer_size) {
272 int new_size = warn_buffer_size + strlen(buf) + 2;
273 char *old_buffer = warn_buffer;
274 if (new_size > WARN_BUFFER_LIMIT) {
275 new_size = WARN_BUFFER_LIMIT;
276 }
277 warn_buffer = myrealloc(warn_buffer, new_size);
278 if (!old_buffer) *warn_buffer = '\0';
279 warn_buffer_size = new_size;
280 }
281 if (strlen(warn_buffer)+strlen(buf)+2 <= warn_buffer_size) {
282 strcat(warn_buffer, buf);
283 strcat(warn_buffer, "\n");
284 }
be371490
TC
285}
286
60715047
TC
287#endif
288
33ca1a7e
TC
289static i_mutex_t mutex;
290
291void
292i_tiff_init(void) {
293 mutex = i_mutex_new();
294}
295
5bb828f1
TC
296static int save_tiff_tags(TIFF *tif, i_img *im);
297
bd8052a6 298static void
8d14daab 299pack_4bit_to(unsigned char *dest, const unsigned char *src, i_img_dim count);
f62b2d84 300
caa833d5
AMH
301
302static toff_t sizeproc(thandle_t x) {
303 return 0;
304}
305
306
02d1d628
AMH
307/*
308=item comp_seek(h, o, w)
309
310Compatability for 64 bit systems like latest freebsd (internal)
311
312 h - tiff handle, cast an io_glue object
313 o - offset
314 w - whence
315
316=cut
317*/
318
319static
320toff_t
321comp_seek(thandle_t h, toff_t o, int w) {
60715047 322 io_glue *ig = ((tiffio_context_t *)h)->ig;
6d5c85a2 323 return (toff_t) i_io_seek(ig, o, w);
02d1d628
AMH
324}
325
e18f39b3
TC
326/*
327=item comp_mmap(thandle_t, tdata_t*, toff_t*)
328
329Dummy mmap stub.
330
331This shouldn't ever be called but newer tifflibs want it anyway.
332
333=cut
334*/
335
336static
337int
338comp_mmap(thandle_t h, tdata_t*p, toff_t*off) {
339 return -1;
340}
341
342/*
343=item comp_munmap(thandle_t h, tdata_t p, toff_t off)
344
345Dummy munmap stub.
346
347This shouldn't ever be called but newer tifflibs want it anyway.
348
349=cut
350*/
351
352static void
353comp_munmap(thandle_t h, tdata_t p, toff_t off) {
354 /* do nothing */
355}
356
6d5c85a2
TC
357static tsize_t
358comp_read(thandle_t h, tdata_t p, tsize_t size) {
60715047 359 return i_io_read(((tiffio_context_t *)h)->ig, p, size);
6d5c85a2
TC
360}
361
362static tsize_t
363comp_write(thandle_t h, tdata_t p, tsize_t size) {
60715047 364 return i_io_write(((tiffio_context_t *)h)->ig, p, size);
6d5c85a2
TC
365}
366
367static int
368comp_close(thandle_t h) {
60715047 369 return i_io_close(((tiffio_context_t *)h)->ig);
6d5c85a2
TC
370}
371
d87dc9a4 372static i_img *read_one_tiff(TIFF *tif, int allow_incomplete) {
02d1d628
AMH
373 i_img *im;
374 uint32 width, height;
bd8052a6 375 uint16 samples_per_pixel;
02d1d628 376 int tiled, error;
faa9b3e7
TC
377 float xres, yres;
378 uint16 resunit;
379 int gotXres, gotYres;
fd9a31d2 380 uint16 photometric;
5bb828f1 381 uint16 bits_per_sample;
bd8052a6
TC
382 uint16 planar_config;
383 uint16 inkset;
384 uint16 compress;
05c9b356 385 uint16 sample_format;
fd9a31d2 386 int i;
bd8052a6
TC
387 read_state_t state;
388 read_setup_t setupf = NULL;
389 read_getter_t getterf = NULL;
390 read_putter_t putterf = NULL;
6b7197d0
TC
391 int channels = MAXCHANNELS;
392 size_t sample_size = ~0; /* force failure if some code doesn't set it */
393 i_img_dim total_pixels;
05c9b356 394 int samples_integral;
02d1d628
AMH
395
396 error = 0;
397
02d1d628
AMH
398 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
399 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
bd8052a6 400 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
02d1d628 401 tiled = TIFFIsTiled(tif);
5bb828f1
TC
402 TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
403 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
bd8052a6
TC
404 TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config);
405 TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
02d1d628 406
05c9b356
TC
407 if (samples_per_pixel == 0) {
408 i_push_error(0, "invalid image: SamplesPerPixel is 0");
409 return NULL;
410 }
411
412 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &sample_format);
413
bd8052a6 414 mm_log((1, "i_readtiff_wiol: width=%d, height=%d, channels=%d\n", width, height, samples_per_pixel));
02d1d628
AMH
415 mm_log((1, "i_readtiff_wiol: %stiled\n", tiled?"":"not "));
416 mm_log((1, "i_readtiff_wiol: %sbyte swapped\n", TIFFIsByteSwapped(tif)?"":"not "));
faa9b3e7 417
6b7197d0
TC
418 total_pixels = width * height;
419 memset(&state, 0, sizeof(state));
420 state.tif = tif;
421 state.allow_incomplete = allow_incomplete;
422 state.width = width;
423 state.height = height;
424 state.bits_per_sample = bits_per_sample;
425 state.samples_per_pixel = samples_per_pixel;
426 state.photometric = photometric;
05c9b356
TC
427 state.sample_signed = sample_format == SAMPLEFORMAT_INT;
428 state.sample_format = sample_format;
429
430 samples_integral = sample_format == SAMPLEFORMAT_UINT
431 || sample_format == SAMPLEFORMAT_INT
432 || sample_format == SAMPLEFORMAT_VOID; /* sample as UINT */
6b7197d0 433
bd8052a6 434 /* yes, this if() is horrible */
05c9b356
TC
435 if (photometric == PHOTOMETRIC_PALETTE && bits_per_sample <= 8
436 && samples_integral) {
bd8052a6
TC
437 setupf = setup_paletted;
438 if (bits_per_sample == 8)
439 putterf = paletted_putter8;
440 else if (bits_per_sample == 4)
441 putterf = paletted_putter4;
442 else
443 mm_log((1, "unsupported paletted bits_per_sample %d\n", bits_per_sample));
6b7197d0
TC
444
445 sample_size = sizeof(i_sample_t);
446 channels = 1;
a50608d2 447 }
bd8052a6
TC
448 else if (bits_per_sample == 16
449 && photometric == PHOTOMETRIC_RGB
05c9b356
TC
450 && samples_per_pixel >= 3
451 && samples_integral) {
bd8052a6
TC
452 setupf = setup_16_rgb;
453 putterf = putter_16;
6b7197d0
TC
454 sample_size = 2;
455 rgb_channels(&state, &channels);
bd8052a6
TC
456 }
457 else if (bits_per_sample == 16
05c9b356
TC
458 && photometric == PHOTOMETRIC_MINISBLACK
459 && samples_integral) {
bd8052a6
TC
460 setupf = setup_16_grey;
461 putterf = putter_16;
6b7197d0
TC
462 sample_size = 2;
463 grey_channels(&state, &channels);
bd8052a6
TC
464 }
465 else if (bits_per_sample == 8
05c9b356
TC
466 && photometric == PHOTOMETRIC_MINISBLACK
467 && samples_integral) {
bd8052a6
TC
468 setupf = setup_8_grey;
469 putterf = putter_8;
6b7197d0
TC
470 sample_size = 1;
471 grey_channels(&state, &channels);
bd8052a6
TC
472 }
473 else if (bits_per_sample == 8
05c9b356
TC
474 && photometric == PHOTOMETRIC_RGB
475 && samples_integral) {
bd8052a6
TC
476 setupf = setup_8_rgb;
477 putterf = putter_8;
6b7197d0
TC
478 sample_size = 1;
479 rgb_channels(&state, &channels);
bd8052a6
TC
480 }
481 else if (bits_per_sample == 32
482 && photometric == PHOTOMETRIC_RGB
483 && samples_per_pixel >= 3) {
484 setupf = setup_32_rgb;
485 putterf = putter_32;
6b7197d0
TC
486 sample_size = sizeof(i_fsample_t);
487 rgb_channels(&state, &channels);
bd8052a6
TC
488 }
489 else if (bits_per_sample == 32
490 && photometric == PHOTOMETRIC_MINISBLACK) {
491 setupf = setup_32_grey;
492 putterf = putter_32;
6b7197d0
TC
493 sample_size = sizeof(i_fsample_t);
494 grey_channels(&state, &channels);
bd8052a6
TC
495 }
496 else if (bits_per_sample == 1
497 && (photometric == PHOTOMETRIC_MINISBLACK
498 || photometric == PHOTOMETRIC_MINISWHITE)
499 && samples_per_pixel == 1) {
500 setupf = setup_bilevel;
501 putterf = putter_bilevel;
6b7197d0
TC
502 sample_size = sizeof(i_palidx);
503 channels = 1;
bd8052a6
TC
504 }
505 else if (bits_per_sample == 8
506 && photometric == PHOTOMETRIC_SEPARATED
507 && inkset == INKSET_CMYK
05c9b356
TC
508 && samples_per_pixel >= 4
509 && samples_integral) {
bd8052a6
TC
510 setupf = setup_cmyk8;
511 putterf = putter_cmyk8;
6b7197d0
TC
512 sample_size = 1;
513 cmyk_channels(&state, &channels);
bd8052a6
TC
514 }
515 else if (bits_per_sample == 16
516 && photometric == PHOTOMETRIC_SEPARATED
517 && inkset == INKSET_CMYK
05c9b356
TC
518 && samples_per_pixel >= 4
519 && samples_integral) {
bd8052a6
TC
520 setupf = setup_cmyk16;
521 putterf = putter_cmyk16;
6b7197d0
TC
522 sample_size = 2;
523 cmyk_channels(&state, &channels);
bd8052a6 524 }
6b7197d0
TC
525 else {
526 int alpha;
527 fallback_rgb_channels(tif, width, height, &channels, &alpha);
528 sample_size = 1;
529 }
530
531 if (!i_int_check_image_file_limits(width, height, channels, sample_size)) {
532 return NULL;
533 }
534
bd8052a6
TC
535 if (tiled) {
536 if (planar_config == PLANARCONFIG_CONTIG)
537 getterf = tile_contig_getter;
538 }
539 else {
540 if (planar_config == PLANARCONFIG_CONTIG)
541 getterf = strip_contig_getter;
542 }
543 if (setupf && getterf && putterf) {
bd8052a6
TC
544
545 if (!setupf(&state))
546 return NULL;
547 if (!getterf(&state, putterf) || !state.pixels_read) {
548 if (state.img)
549 i_img_destroy(state.img);
550 if (state.raster)
551 _TIFFfree(state.raster);
552 if (state.line_buf)
553 myfree(state.line_buf);
554
555 return NULL;
556 }
a50608d2 557
bd8052a6
TC
558 if (allow_incomplete && state.pixels_read < total_pixels) {
559 i_tags_setn(&(state.img->tags), "i_incomplete", 1);
560 i_tags_setn(&(state.img->tags), "i_lines_read",
561 state.pixels_read / width);
562 }
563 im = state.img;
564
565 if (state.raster)
566 _TIFFfree(state.raster);
567 if (state.line_buf)
568 myfree(state.line_buf);
5bb828f1
TC
569 }
570 else {
bd8052a6
TC
571 if (tiled) {
572 im = read_one_rgb_tiled(tif, width, height, allow_incomplete);
573 }
574 else {
575 im = read_one_rgb_lines(tif, width, height, allow_incomplete);
576 }
5bb828f1 577 }
8c3af7b3
TC
578
579 if (!im)
580 return NULL;
f00e06a0
TC
581
582 /* general metadata */
e5ee047b
TC
583 i_tags_setn(&im->tags, "tiff_bitspersample", bits_per_sample);
584 i_tags_setn(&im->tags, "tiff_photometric", photometric);
bd8052a6 585 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
5bb828f1 586
fd9a31d2 587 /* resolution tags */
5bb828f1 588 TIFFGetFieldDefaulted(tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
faa9b3e7
TC
589 gotXres = TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres);
590 gotYres = TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres);
591 if (gotXres || gotYres) {
592 if (!gotXres)
593 xres = yres;
594 else if (!gotYres)
595 yres = xres;
e5ee047b 596 i_tags_setn(&im->tags, "tiff_resolutionunit", resunit);
faa9b3e7
TC
597 if (resunit == RESUNIT_CENTIMETER) {
598 /* from dots per cm to dpi */
599 xres *= 2.54;
600 yres *= 2.54;
e5ee047b 601 i_tags_set(&im->tags, "tiff_resolutionunit_name", "centimeter", -1);
faa9b3e7 602 }
3cff89e2 603 else if (resunit == RESUNIT_NONE) {
e5ee047b
TC
604 i_tags_setn(&im->tags, "i_aspect_only", 1);
605 i_tags_set(&im->tags, "tiff_resolutionunit_name", "none", -1);
3cff89e2
TC
606 }
607 else if (resunit == RESUNIT_INCH) {
e5ee047b 608 i_tags_set(&im->tags, "tiff_resolutionunit_name", "inch", -1);
3cff89e2
TC
609 }
610 else {
e5ee047b 611 i_tags_set(&im->tags, "tiff_resolutionunit_name", "unknown", -1);
3cff89e2 612 }
2e41e30b
TC
613 /* tifflib doesn't seem to provide a way to get to the original rational
614 value of these, which would let me provide a more reasonable
615 precision. So make up a number. */
616 i_tags_set_float2(&im->tags, "i_xres", 0, xres, 6);
617 i_tags_set_float2(&im->tags, "i_yres", 0, yres, 6);
faa9b3e7 618 }
fd9a31d2
TC
619
620 /* Text tags */
621 for (i = 0; i < text_tag_count; ++i) {
622 char *data;
623 if (TIFFGetField(tif, text_tag_names[i].tag, &data)) {
624 mm_log((1, "i_readtiff_wiol: tag %d has value %s\n",
625 text_tag_names[i].tag, data));
e5ee047b 626 i_tags_set(&im->tags, text_tag_names[i].name, data, -1);
fd9a31d2
TC
627 }
628 }
8c3af7b3 629
e5ee047b 630 i_tags_set(&im->tags, "i_format", "tiff", 4);
60715047
TC
631#ifdef USE_EXT_WARN_HANDLER
632 {
633 tiffio_context_t *ctx = TIFFClientdata(tif);
634 if (ctx->warn_buffer && ctx->warn_buffer[0]) {
635 i_tags_set(&im->tags, "i_warning", ctx->warn_buffer, -1);
636 ctx->warn_buffer[0] = '\0';
637 }
638 }
639#else
ffeb4a67 640 if (warn_buffer && *warn_buffer) {
e5ee047b 641 i_tags_set(&im->tags, "i_warning", warn_buffer, -1);
ffeb4a67
TC
642 *warn_buffer = '\0';
643 }
60715047 644#endif
bd8052a6
TC
645
646 for (i = 0; i < compress_value_count; ++i) {
647 if (compress_values[i].tag == compress) {
e5ee047b 648 i_tags_set(&im->tags, "tiff_compression", compress_values[i].name, -1);
bd8052a6 649 break;
5bb828f1 650 }
5bb828f1 651 }
05c9b356
TC
652
653 if (TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sample_format)) {
654 /* only set the tag if the the TIFF tag is present */
655 i_tags_setn(&im->tags, "tiff_sample_format", sample_format);
656
657 for (i = 0; i < sample_format_value_count; ++i) {
658 if (sample_format_values[i].tag == sample_format) {
659 i_tags_set(&im->tags, "tiff_sample_format_name",
660 sample_format_values[i].name, -1);
661 break;
662 }
663 }
664 }
665
10461f9a
TC
666 return im;
667}
668
669/*
05c9b356 670=item i_readtiff_wiol(ig, allow_incomplete, page)
10461f9a
TC
671
672=cut
673*/
674i_img*
d87dc9a4 675i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
10461f9a
TC
676 TIFF* tif;
677 TIFFErrorHandler old_handler;
be371490 678 TIFFErrorHandler old_warn_handler;
60715047
TC
679#ifdef USE_EXT_WARN_HANDLER
680 TIFFErrorHandlerExt old_ext_warn_handler;
681#endif
10461f9a 682 i_img *im;
69287763 683 int current_page;
60715047 684 tiffio_context_t ctx;
e482e0b3 685
33ca1a7e
TC
686 i_mutex_lock(mutex);
687
10461f9a
TC
688 i_clear_error();
689 old_handler = TIFFSetErrorHandler(error_handler);
60715047
TC
690#ifdef USE_EXT_WARN_HANDLER
691 old_warn_handler = TIFFSetWarningHandler(NULL);
692 old_ext_warn_handler = TIFFSetWarningHandlerExt(warn_handler_ex);
693#else
be371490 694 old_warn_handler = TIFFSetWarningHandler(warn_handler);
ffeb4a67
TC
695 if (warn_buffer)
696 *warn_buffer = '\0';
60715047 697#endif
10461f9a
TC
698
699 /* Add code to get the filename info from the iolayer */
700 /* Also add code to check for mmapped code */
701
d87dc9a4 702 mm_log((1, "i_readtiff_wiol(ig %p, allow_incomplete %d, page %d)\n", ig, allow_incomplete, page));
10461f9a 703
60715047 704 tiffio_context_init(&ctx, ig);
10461f9a
TC
705 tif = TIFFClientOpen("(Iolayer)",
706 "rm",
60715047 707 (thandle_t) &ctx,
6d5c85a2
TC
708 comp_read,
709 comp_write,
710 comp_seek,
711 comp_close,
712 sizeproc,
713 comp_mmap,
714 comp_munmap);
10461f9a
TC
715
716 if (!tif) {
717 mm_log((1, "i_readtiff_wiol: Unable to open tif file\n"));
2691d220 718 i_push_error(0, "Error opening file");
10461f9a 719 TIFFSetErrorHandler(old_handler);
be371490 720 TIFFSetWarningHandler(old_warn_handler);
60715047
TC
721#ifdef USE_EXT_WARN_HANDLER
722 TIFFSetWarningHandlerExt(old_ext_warn_handler);
723#endif
724 tiffio_context_final(&ctx);
33ca1a7e 725 i_mutex_unlock(mutex);
10461f9a
TC
726 return NULL;
727 }
728
69287763
TC
729 for (current_page = 0; current_page < page; ++current_page) {
730 if (!TIFFReadDirectory(tif)) {
8f8bd9aa
TC
731 mm_log((1, "i_readtiff_wiol: Unable to switch to directory %d\n", page));
732 i_push_errorf(0, "could not switch to page %d", page);
733 TIFFSetErrorHandler(old_handler);
734 TIFFSetWarningHandler(old_warn_handler);
60715047
TC
735#ifdef USE_EXT_WARN_HANDLER
736 TIFFSetWarningHandlerExt(old_ext_warn_handler);
737#endif
01f2d357 738 TIFFClose(tif);
60715047 739 tiffio_context_final(&ctx);
33ca1a7e 740 i_mutex_unlock(mutex);
8f8bd9aa
TC
741 return NULL;
742 }
743 }
744
d87dc9a4 745 im = read_one_tiff(tif, allow_incomplete);
10461f9a 746
02d1d628 747 if (TIFFLastDirectory(tif)) mm_log((1, "Last directory of tiff file\n"));
5bb828f1 748 TIFFSetErrorHandler(old_handler);
be371490 749 TIFFSetWarningHandler(old_warn_handler);
60715047
TC
750#ifdef USE_EXT_WARN_HANDLER
751 TIFFSetWarningHandlerExt(old_ext_warn_handler);
752#endif
5bb828f1 753 TIFFClose(tif);
60715047 754 tiffio_context_final(&ctx);
33ca1a7e 755 i_mutex_unlock(mutex);
60715047 756
02d1d628
AMH
757 return im;
758}
759
10461f9a 760/*
e5ee047b 761=item i_readtiff_multi_wiol(ig, *count)
02d1d628 762
10461f9a 763Reads multiple images from a TIFF.
02d1d628 764
10461f9a
TC
765=cut
766*/
767i_img**
e5ee047b 768i_readtiff_multi_wiol(io_glue *ig, int *count) {
10461f9a
TC
769 TIFF* tif;
770 TIFFErrorHandler old_handler;
be371490 771 TIFFErrorHandler old_warn_handler;
60715047
TC
772#ifdef USE_EXT_WARN_HANDLER
773 TIFFErrorHandlerExt old_ext_warn_handler;
774#endif
10461f9a
TC
775 i_img **results = NULL;
776 int result_alloc = 0;
60715047 777 tiffio_context_t ctx;
e482e0b3 778
33ca1a7e
TC
779 i_mutex_lock(mutex);
780
10461f9a
TC
781 i_clear_error();
782 old_handler = TIFFSetErrorHandler(error_handler);
60715047
TC
783#ifdef USE_EXT_WARN_HANDLER
784 old_warn_handler = TIFFSetWarningHandler(NULL);
785 old_ext_warn_handler = TIFFSetWarningHandlerExt(warn_handler_ex);
786#else
be371490 787 old_warn_handler = TIFFSetWarningHandler(warn_handler);
ffeb4a67
TC
788 if (warn_buffer)
789 *warn_buffer = '\0';
60715047
TC
790#endif
791
792 tiffio_context_init(&ctx, ig);
02d1d628 793
10461f9a
TC
794 /* Add code to get the filename info from the iolayer */
795 /* Also add code to check for mmapped code */
02d1d628 796
5e84d110 797 mm_log((1, "i_readtiff_wiol(ig %p)\n", ig));
10461f9a
TC
798
799 tif = TIFFClientOpen("(Iolayer)",
800 "rm",
60715047 801 (thandle_t) &ctx,
6d5c85a2
TC
802 comp_read,
803 comp_write,
804 comp_seek,
805 comp_close,
806 sizeproc,
807 comp_mmap,
808 comp_munmap);
10461f9a
TC
809
810 if (!tif) {
811 mm_log((1, "i_readtiff_wiol: Unable to open tif file\n"));
2691d220 812 i_push_error(0, "Error opening file");
10461f9a 813 TIFFSetErrorHandler(old_handler);
be371490 814 TIFFSetWarningHandler(old_warn_handler);
60715047
TC
815#ifdef USE_EXT_WARN_HANDLER
816 TIFFSetWarningHandlerExt(old_ext_warn_handler);
817#endif
818 tiffio_context_final(&ctx);
33ca1a7e 819 i_mutex_unlock(mutex);
10461f9a
TC
820 return NULL;
821 }
02d1d628 822
10461f9a
TC
823 *count = 0;
824 do {
9c106321 825 i_img *im = read_one_tiff(tif, 0);
10461f9a
TC
826 if (!im)
827 break;
828 if (++*count > result_alloc) {
829 if (result_alloc == 0) {
830 result_alloc = 5;
831 results = mymalloc(result_alloc * sizeof(i_img *));
832 }
833 else {
834 i_img **newresults;
835 result_alloc *= 2;
836 newresults = myrealloc(results, result_alloc * sizeof(i_img *));
be371490
TC
837 if (!newresults) {
838 i_img_destroy(im); /* don't leak it */
839 break;
840 }
841 results = newresults;
10461f9a
TC
842 }
843 }
844 results[*count-1] = im;
69287763 845 } while (TIFFReadDirectory(tif));
10461f9a 846
be371490 847 TIFFSetWarningHandler(old_warn_handler);
10461f9a 848 TIFFSetErrorHandler(old_handler);
60715047
TC
849#ifdef USE_EXT_WARN_HANDLER
850 TIFFSetWarningHandlerExt(old_ext_warn_handler);
851#endif
10461f9a 852 TIFFClose(tif);
60715047 853 tiffio_context_final(&ctx);
33ca1a7e 854 i_mutex_unlock(mutex);
60715047 855
10461f9a
TC
856 return results;
857}
02d1d628
AMH
858
859undef_int
10461f9a
TC
860i_writetiff_low_faxable(TIFF *tif, i_img *im, int fine) {
861 uint32 width, height;
862 unsigned char *linebuf = NULL;
863 uint32 y;
864 int rc;
865 uint32 x;
10461f9a
TC
866 uint32 rowsperstrip;
867 float vres = fine ? 196 : 98;
868 int luma_chan;
869
870 width = im->xsize;
871 height = im->ysize;
872
8d14daab
TC
873 if (width != im->xsize || height != im->ysize) {
874 i_push_error(0, "image too large for TIFF");
875 return 0;
876 }
877
10461f9a
TC
878 switch (im->channels) {
879 case 1:
880 case 2:
881 luma_chan = 0;
882 break;
883 case 3:
884 case 4:
885 luma_chan = 1;
886 break;
887 default:
888 /* This means a colorspace we don't handle yet */
889 mm_log((1, "i_writetiff_wiol_faxable: don't handle %d channel images.\n", im->channels));
890 return 0;
891 }
892
893 /* Add code to get the filename info from the iolayer */
894 /* Also add code to check for mmapped code */
895
896
897 mm_log((1, "i_writetiff_wiol_faxable: width=%d, height=%d, channels=%d\n", width, height, im->channels));
898
899 if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width) )
900 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField width=%d failed\n", width)); return 0; }
901 if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height) )
902 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField length=%d failed\n", height)); return 0; }
903 if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1))
904 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField samplesperpixel=1 failed\n")); return 0; }
905 if (!TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT))
906 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField Orientation=topleft\n")); return 0; }
907 if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1) )
908 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField bitpersample=1\n")); return 0; }
909 if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG))
910 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField planarconfig\n")); return 0; }
799d55a6 911 if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE))
10461f9a
TC
912 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField photometric=%d\n", PHOTOMETRIC_MINISBLACK)); return 0; }
913 if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, 3))
914 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField compression=3\n")); return 0; }
915
916 linebuf = (unsigned char *)_TIFFmalloc( TIFFScanlineSize(tif) );
917
918 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
919 mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField rowsperstrip=-1\n")); return 0; }
920
921 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
922 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rc);
923
924 mm_log((1, "i_writetiff_wiol_faxable: TIFFGetField rowsperstrip=%d\n", rowsperstrip));
925 mm_log((1, "i_writetiff_wiol_faxable: TIFFGetField scanlinesize=%d\n", TIFFScanlineSize(tif) ));
926 mm_log((1, "i_writetiff_wiol_faxable: TIFFGetField planarconfig=%d == %d\n", rc, PLANARCONFIG_CONTIG));
927
928 if (!TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)204))
929 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField Xresolution=204\n")); return 0; }
930 if (!TIFFSetField(tif, TIFFTAG_YRESOLUTION, vres))
931 { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField Yresolution=196\n")); return 0; }
932 if (!TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)) {
933 mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField ResolutionUnit=%d\n", RESUNIT_INCH)); return 0;
934 }
935
936 if (!save_tiff_tags(tif, im)) {
937 return 0;
938 }
939
940 for (y=0; y<height; y++) {
941 int linebufpos=0;
942 for(x=0; x<width; x+=8) {
943 int bits;
944 int bitpos;
945 i_sample_t luma[8];
946 uint8 bitval = 128;
947 linebuf[linebufpos]=0;
948 bits = width-x; if(bits>8) bits=8;
949 i_gsamp(im, x, x+8, y, luma, &luma_chan, 1);
950 for(bitpos=0;bitpos<bits;bitpos++) {
799d55a6 951 linebuf[linebufpos] |= ((luma[bitpos] < 128) ? bitval : 0);
10461f9a
TC
952 bitval >>= 1;
953 }
954 linebufpos++;
955 }
956 if (TIFFWriteScanline(tif, linebuf, y, 0) < 0) {
957 mm_log((1, "i_writetiff_wiol_faxable: TIFFWriteScanline failed.\n"));
958 break;
959 }
960 }
961 if (linebuf) _TIFFfree(linebuf);
962
963 return 1;
964}
965
bd8052a6
TC
966static uint16
967find_compression(char const *name, uint16 *compress) {
968 int i;
02d1d628 969
bd8052a6
TC
970 for (i = 0; i < compress_value_count; ++i) {
971 if (strcmp(compress_values[i].name, name) == 0) {
972 *compress = (uint16)compress_values[i].tag;
973 return 1;
f62b2d84 974 }
02d1d628 975 }
bd8052a6 976 *compress = COMPRESSION_NONE;
02d1d628 977
bd8052a6
TC
978 return 0;
979}
02d1d628 980
bd8052a6
TC
981static uint16
982get_compression(i_img *im, uint16 def_compress) {
983 int entry;
984 int value;
985
986 if (i_tags_find(&im->tags, "tiff_compression", 0, &entry)
987 && im->tags.tags[entry].data) {
988 uint16 compress;
989 if (find_compression(im->tags.tags[entry].data, &compress)
f8d72f20 990 && myTIFFIsCODECConfigured(compress))
bd8052a6 991 return compress;
10461f9a 992 }
bd8052a6
TC
993 if (i_tags_get_int(&im->tags, "tiff_compression", 0, &value)) {
994 if ((uint16)value == value
f8d72f20 995 && myTIFFIsCODECConfigured((uint16)value))
bd8052a6 996 return (uint16)value;
10461f9a 997 }
bd8052a6
TC
998
999 return def_compress;
1000}
1001
1002int
1003i_tiff_has_compression(const char *name) {
1004 uint16 compress;
1005
1006 if (!find_compression(name, &compress))
1007 return 0;
1008
f8d72f20 1009 return myTIFFIsCODECConfigured(compress);
bd8052a6
TC
1010}
1011
1012static int
1013set_base_tags(TIFF *tif, i_img *im, uint16 compress, uint16 photometric,
1014 uint16 bits_per_sample, uint16 samples_per_pixel) {
1015 double xres, yres;
1016 int resunit;
1017 int got_xres, got_yres;
1018 int aspect_only;
1019
1020 if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, im->xsize)) {
1021 i_push_error(0, "write TIFF: setting width tag");
1022 return 0;
10461f9a 1023 }
bd8052a6
TC
1024 if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, im->ysize)) {
1025 i_push_error(0, "write TIFF: setting length tag");
1026 return 0;
10461f9a 1027 }
bd8052a6
TC
1028 if (!TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)) {
1029 i_push_error(0, "write TIFF: setting orientation tag");
1030 return 0;
10461f9a 1031 }
bd8052a6
TC
1032 if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
1033 i_push_error(0, "write TIFF: setting planar configuration tag");
1034 return 0;
02d1d628 1035 }
bd8052a6
TC
1036 if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric)) {
1037 i_push_error(0, "write TIFF: setting photometric tag");
1038 return 0;
f62b2d84 1039 }
bd8052a6
TC
1040 if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, compress)) {
1041 i_push_error(0, "write TIFF: setting compression tag");
1042 return 0;
f62b2d84 1043 }
bd8052a6
TC
1044 if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample)) {
1045 i_push_error(0, "write TIFF: setting bits per sample tag");
f62b2d84
TC
1046 return 0;
1047 }
bd8052a6
TC
1048 if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel)) {
1049 i_push_error(0, "write TIFF: setting samples per pixel tag");
02d1d628
AMH
1050 return 0;
1051 }
02d1d628 1052
faa9b3e7
TC
1053 got_xres = i_tags_get_float(&im->tags, "i_xres", 0, &xres);
1054 got_yres = i_tags_get_float(&im->tags, "i_yres", 0, &yres);
1055 if (!i_tags_get_int(&im->tags, "i_aspect_only", 0,&aspect_only))
1056 aspect_only = 0;
1057 if (!i_tags_get_int(&im->tags, "tiff_resolutionunit", 0, &resunit))
1058 resunit = RESUNIT_INCH;
1059 if (got_xres || got_yres) {
1060 if (!got_xres)
1061 xres = yres;
1062 else if (!got_yres)
1063 yres = xres;
1064 if (aspect_only) {
1065 resunit = RESUNIT_NONE;
1066 }
1067 else {
1068 if (resunit == RESUNIT_CENTIMETER) {
1069 xres /= 2.54;
1070 yres /= 2.54;
1071 }
1072 else {
1073 resunit = RESUNIT_INCH;
1074 }
1075 }
1076 if (!TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)xres)) {
bd8052a6 1077 i_push_error(0, "write TIFF: setting xresolution tag");
faa9b3e7
TC
1078 return 0;
1079 }
1080 if (!TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)yres)) {
bd8052a6 1081 i_push_error(0, "write TIFF: setting yresolution tag");
faa9b3e7
TC
1082 return 0;
1083 }
1084 if (!TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (uint16)resunit)) {
bd8052a6 1085 i_push_error(0, "write TIFF: setting resolutionunit tag");
faa9b3e7 1086 return 0;
02d1d628
AMH
1087 }
1088 }
fd9a31d2 1089
bd8052a6
TC
1090 return 1;
1091}
1092
1093static int
1094write_one_bilevel(TIFF *tif, i_img *im, int zero_is_white) {
1095 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1096 uint16 photometric;
1097 unsigned char *in_row;
1098 unsigned char *out_row;
1099 unsigned out_size;
8d14daab 1100 i_img_dim x, y;
bd8052a6
TC
1101 int invert;
1102
1103 mm_log((1, "tiff - write_one_bilevel(tif %p, im %p, zero_is_white %d)\n",
1104 tif, im, zero_is_white));
1105
1106 /* ignore a silly choice */
1107 if (compress == COMPRESSION_JPEG)
1108 compress = COMPRESSION_PACKBITS;
1109
1110 switch (compress) {
1111 case COMPRESSION_CCITTRLE:
1112 case COMPRESSION_CCITTFAX3:
1113 case COMPRESSION_CCITTFAX4:
1114 /* natural fax photometric */
1115 photometric = PHOTOMETRIC_MINISWHITE;
1116 break;
1117
1118 default:
1119 /* natural for most computer images */
1120 photometric = PHOTOMETRIC_MINISBLACK;
1121 break;
fd9a31d2
TC
1122 }
1123
bd8052a6
TC
1124 if (!set_base_tags(tif, im, compress, photometric, 1, 1))
1125 return 0;
1126
1127 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
1128 i_push_error(0, "write TIFF: setting rows per strip tag");
1129 return 0;
f62b2d84 1130 }
bd8052a6
TC
1131
1132 out_size = TIFFScanlineSize(tif);
1133 out_row = (unsigned char *)_TIFFmalloc( out_size );
1134 in_row = mymalloc(im->xsize);
1135
1136 invert = (photometric == PHOTOMETRIC_MINISWHITE) != (zero_is_white != 0);
1137
1138 for (y = 0; y < im->ysize; ++y) {
1139 int mask = 0x80;
1140 unsigned char *outp = out_row;
1141 memset(out_row, 0, out_size);
1142 i_gpal(im, 0, im->xsize, y, in_row);
1143 for (x = 0; x < im->xsize; ++x) {
1144 if (invert ? !in_row[x] : in_row[x]) {
1145 *outp |= mask;
f62b2d84 1146 }
bd8052a6
TC
1147 mask >>= 1;
1148 if (!mask) {
1149 ++outp;
1150 mask = 0x80;
f62b2d84 1151 }
02d1d628 1152 }
bd8052a6
TC
1153 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1154 _TIFFfree(out_row);
1155 myfree(in_row);
1156 i_push_error(0, "write TIFF: write scan line failed");
1157 return 0;
1158 }
02d1d628 1159 }
d2dfdcc9 1160
bd8052a6
TC
1161 _TIFFfree(out_row);
1162 myfree(in_row);
d2dfdcc9 1163
bd8052a6
TC
1164 return 1;
1165}
d2dfdcc9 1166
bd8052a6
TC
1167static int
1168set_palette(TIFF *tif, i_img *im, int size) {
1169 int count;
1170 uint16 *colors;
1171 uint16 *out[3];
1172 i_color c;
1173 int i, ch;
1174
1175 colors = (uint16 *)_TIFFmalloc(sizeof(uint16) * 3 * size);
1176 out[0] = colors;
1177 out[1] = colors + size;
1178 out[2] = colors + 2 * size;
1179
1180 count = i_colorcount(im);
1181 for (i = 0; i < count; ++i) {
1182 i_getcolors(im, i, &c, 1);
1183 for (ch = 0; ch < 3; ++ch)
1184 out[ch][i] = c.channel[ch] * 257;
1185 }
1186 for (; i < size; ++i) {
1187 for (ch = 0; ch < 3; ++ch)
1188 out[ch][i] = 0;
1189 }
1190 if (!TIFFSetField(tif, TIFFTAG_COLORMAP, out[0], out[1], out[2])) {
1191 _TIFFfree(colors);
1192 i_push_error(0, "write TIFF: setting color map");
1193 return 0;
1194 }
1195 _TIFFfree(colors);
1196
1197 return 1;
1198}
d2dfdcc9 1199
bd8052a6
TC
1200static int
1201write_one_paletted8(TIFF *tif, i_img *im) {
1202 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1203 unsigned char *out_row;
1204 unsigned out_size;
8d14daab 1205 i_img_dim y;
d2dfdcc9 1206
bd8052a6 1207 mm_log((1, "tiff - write_one_paletted8(tif %p, im %p)\n", tif, im));
2691d220 1208
bd8052a6
TC
1209 /* ignore a silly choice */
1210 if (compress == COMPRESSION_JPEG ||
1211 compress == COMPRESSION_CCITTRLE ||
1212 compress == COMPRESSION_CCITTFAX3 ||
1213 compress == COMPRESSION_CCITTFAX4)
1214 compress = COMPRESSION_PACKBITS;
d2dfdcc9 1215
bd8052a6
TC
1216 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
1217 i_push_error(0, "write TIFF: setting rows per strip tag");
1218 return 0;
1219 }
10461f9a 1220
bd8052a6
TC
1221 if (!set_base_tags(tif, im, compress, PHOTOMETRIC_PALETTE, 8, 1))
1222 return 0;
10461f9a 1223
bd8052a6 1224 if (!set_palette(tif, im, 256))
d2dfdcc9 1225 return 0;
d2dfdcc9 1226
bd8052a6
TC
1227 out_size = TIFFScanlineSize(tif);
1228 out_row = (unsigned char *)_TIFFmalloc( out_size );
1229
1230 for (y = 0; y < im->ysize; ++y) {
1231 i_gpal(im, 0, im->xsize, y, out_row);
1232 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1233 _TIFFfree(out_row);
1234 i_push_error(0, "write TIFF: write scan line failed");
10461f9a
TC
1235 return 0;
1236 }
bd8052a6 1237 }
10461f9a 1238
bd8052a6
TC
1239 _TIFFfree(out_row);
1240
1241 return 1;
1242}
1243
1244static int
1245write_one_paletted4(TIFF *tif, i_img *im) {
1246 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1247 unsigned char *in_row;
1248 unsigned char *out_row;
8d14daab
TC
1249 size_t out_size;
1250 i_img_dim y;
bd8052a6
TC
1251
1252 mm_log((1, "tiff - write_one_paletted4(tif %p, im %p)\n", tif, im));
1253
1254 /* ignore a silly choice */
1255 if (compress == COMPRESSION_JPEG ||
1256 compress == COMPRESSION_CCITTRLE ||
1257 compress == COMPRESSION_CCITTFAX3 ||
1258 compress == COMPRESSION_CCITTFAX4)
1259 compress = COMPRESSION_PACKBITS;
1260
1261 if (!set_base_tags(tif, im, compress, PHOTOMETRIC_PALETTE, 4, 1))
1262 return 0;
1263
1264 if (!set_palette(tif, im, 16))
1265 return 0;
1266
1267 if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1))) {
1268 i_push_error(0, "write TIFF: setting rows per strip tag");
1269 return 0;
1270 }
1271
1272 in_row = mymalloc(im->xsize);
1273 out_size = TIFFScanlineSize(tif);
1274 out_row = (unsigned char *)_TIFFmalloc( out_size );
1275
1276 for (y = 0; y < im->ysize; ++y) {
1277 i_gpal(im, 0, im->xsize, y, in_row);
1278 memset(out_row, 0, out_size);
1279 pack_4bit_to(out_row, in_row, im->xsize);
1280 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1281 _TIFFfree(out_row);
1282 i_push_error(0, "write TIFF: write scan line failed");
1283 return 0;
1284 }
1285 }
1286
1287 myfree(in_row);
1288 _TIFFfree(out_row);
1289
1290 return 1;
1291}
1292
1293static int
1294set_direct_tags(TIFF *tif, i_img *im, uint16 compress,
1295 uint16 bits_per_sample) {
1296 uint16 extras = EXTRASAMPLE_ASSOCALPHA;
1297 uint16 extra_count = im->channels == 2 || im->channels == 4;
1298 uint16 photometric = im->channels >= 3 ?
1299 PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
1300
1301 if (!set_base_tags(tif, im, compress, photometric, bits_per_sample,
1302 im->channels)) {
1303 return 0;
1304 }
1305
1306 if (extra_count) {
1307 if (!TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, extra_count, &extras)) {
1308 i_push_error(0, "write TIFF: setting extra samples tag");
1309 return 0;
1310 }
1311 }
1312
1313 if (compress == COMPRESSION_JPEG) {
1314 int jpeg_quality;
1315 if (i_tags_get_int(&im->tags, "tiff_jpegquality", 0, &jpeg_quality)
1316 && jpeg_quality >= 0 && jpeg_quality <= 100) {
1317 if (!TIFFSetField(tif, TIFFTAG_JPEGQUALITY, jpeg_quality)) {
1318 i_push_error(0, "write TIFF: setting jpeg quality pseudo-tag");
1319 return 0;
1320 }
1321 }
1322 }
1323
1324 return 1;
1325}
1326
1327static int
1328write_one_32(TIFF *tif, i_img *im) {
1329 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1330 unsigned *in_row;
1331 size_t out_size;
1332 uint32 *out_row;
8d14daab 1333 i_img_dim y;
bd8052a6
TC
1334 size_t sample_count = im->xsize * im->channels;
1335 size_t sample_index;
1336
1337 mm_log((1, "tiff - write_one_32(tif %p, im %p)\n", tif, im));
1338
1339 /* only 8 and 12 bit samples are supported by jpeg compression */
1340 if (compress == COMPRESSION_JPEG)
1341 compress = COMPRESSION_PACKBITS;
1342
1343 if (!set_direct_tags(tif, im, compress, 32))
1344 return 0;
1345
1346 in_row = mymalloc(sample_count * sizeof(unsigned));
1347 out_size = TIFFScanlineSize(tif);
1348 out_row = (uint32 *)_TIFFmalloc( out_size );
1349
1350 for (y = 0; y < im->ysize; ++y) {
1351 if (i_gsamp_bits(im, 0, im->xsize, y, in_row, NULL, im->channels, 32) <= 0) {
1352 i_push_error(0, "Cannot read 32-bit samples");
1353 return 0;
1354 }
1355 for (sample_index = 0; sample_index < sample_count; ++sample_index)
1356 out_row[sample_index] = in_row[sample_index];
1357 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1358 myfree(in_row);
1359 _TIFFfree(out_row);
1360 i_push_error(0, "write TIFF: write scan line failed");
1361 return 0;
1362 }
1363 }
1364
1365 myfree(in_row);
1366 _TIFFfree(out_row);
1367
1368 return 1;
1369}
1370
1371static int
1372write_one_16(TIFF *tif, i_img *im) {
1373 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1374 unsigned *in_row;
1375 size_t out_size;
1376 uint16 *out_row;
8d14daab 1377 i_img_dim y;
bd8052a6
TC
1378 size_t sample_count = im->xsize * im->channels;
1379 size_t sample_index;
1380
1381 mm_log((1, "tiff - write_one_16(tif %p, im %p)\n", tif, im));
1382
1383 /* only 8 and 12 bit samples are supported by jpeg compression */
1384 if (compress == COMPRESSION_JPEG)
1385 compress = COMPRESSION_PACKBITS;
1386
1387 if (!set_direct_tags(tif, im, compress, 16))
1388 return 0;
1389
1390 in_row = mymalloc(sample_count * sizeof(unsigned));
1391 out_size = TIFFScanlineSize(tif);
1392 out_row = (uint16 *)_TIFFmalloc( out_size );
1393
1394 for (y = 0; y < im->ysize; ++y) {
1395 if (i_gsamp_bits(im, 0, im->xsize, y, in_row, NULL, im->channels, 16) <= 0) {
1396 i_push_error(0, "Cannot read 16-bit samples");
1397 return 0;
1398 }
1399 for (sample_index = 0; sample_index < sample_count; ++sample_index)
1400 out_row[sample_index] = in_row[sample_index];
1401 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1402 myfree(in_row);
1403 _TIFFfree(out_row);
1404 i_push_error(0, "write TIFF: write scan line failed");
1405 return 0;
1406 }
1407 }
1408
1409 myfree(in_row);
1410 _TIFFfree(out_row);
1411
1412 return 1;
1413}
1414
1415static int
1416write_one_8(TIFF *tif, i_img *im) {
1417 uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
1418 size_t out_size;
1419 unsigned char *out_row;
8d14daab 1420 i_img_dim y;
bd8052a6
TC
1421 size_t sample_count = im->xsize * im->channels;
1422
1423 mm_log((1, "tiff - write_one_8(tif %p, im %p)\n", tif, im));
1424
1425 if (!set_direct_tags(tif, im, compress, 8))
1426 return 0;
1427
1428 out_size = TIFFScanlineSize(tif);
1429 if (out_size < sample_count)
1430 out_size = sample_count;
1431 out_row = (unsigned char *)_TIFFmalloc( out_size );
1432
1433 for (y = 0; y < im->ysize; ++y) {
1434 if (i_gsamp(im, 0, im->xsize, y, out_row, NULL, im->channels) <= 0) {
1435 i_push_error(0, "Cannot read 8-bit samples");
1436 return 0;
1437 }
1438 if (TIFFWriteScanline(tif, out_row, y, 0) < 0) {
1439 _TIFFfree(out_row);
1440 i_push_error(0, "write TIFF: write scan line failed");
1441 return 0;
1442 }
1443 }
1444 _TIFFfree(out_row);
1445
1446 return 1;
1447}
1448
1449static int
1450i_writetiff_low(TIFF *tif, i_img *im) {
1451 uint32 width, height;
1452 uint16 channels;
1453 int zero_is_white;
1454
1455 width = im->xsize;
1456 height = im->ysize;
1457 channels = im->channels;
1458
8d14daab
TC
1459 if (width != im->xsize || height != im->ysize) {
1460 i_push_error(0, "image too large for TIFF");
1461 return 0;
1462 }
1463
bd8052a6
TC
1464 mm_log((1, "i_writetiff_low: width=%d, height=%d, channels=%d, bits=%d\n", width, height, channels, im->bits));
1465 if (im->type == i_palette_type) {
1466 mm_log((1, "i_writetiff_low: paletted, colors=%d\n", i_colorcount(im)));
1467 }
1468
1469 if (i_img_is_monochrome(im, &zero_is_white)) {
1470 if (!write_one_bilevel(tif, im, zero_is_white))
1471 return 0;
1472 }
1473 else if (im->type == i_palette_type) {
1474 if (i_colorcount(im) <= 16) {
1475 if (!write_one_paletted4(tif, im))
1476 return 0;
1477 }
1478 else {
1479 if (!write_one_paletted8(tif, im))
1480 return 0;
1481 }
1482 }
1483 else if (im->bits > 16) {
1484 if (!write_one_32(tif, im))
1485 return 0;
1486 }
1487 else if (im->bits > 8) {
1488 if (!write_one_16(tif, im))
1489 return 0;
1490 }
1491 else {
1492 if (!write_one_8(tif, im))
1493 return 0;
1494 }
1495
1496 if (!save_tiff_tags(tif, im))
1497 return 0;
1498
1499 return 1;
1500}
1501
1502/*
1503=item i_writetiff_multi_wiol(ig, imgs, count, fine_mode)
1504
1505Stores an image in the iolayer object.
1506
1507 ig - io_object that defines source to write to
1508 imgs,count - the images to write
1509
1510=cut
1511*/
1512
1513undef_int
1514i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
1515 TIFF* tif;
1516 TIFFErrorHandler old_handler;
1517 int i;
60715047 1518 tiffio_context_t ctx;
e482e0b3 1519
33ca1a7e
TC
1520 i_mutex_lock(mutex);
1521
bd8052a6
TC
1522 old_handler = TIFFSetErrorHandler(error_handler);
1523
bd8052a6 1524 i_clear_error();
8d14daab 1525 mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n",
bd8052a6
TC
1526 ig, imgs, count));
1527
60715047 1528 tiffio_context_init(&ctx, ig);
bd8052a6
TC
1529
1530 tif = TIFFClientOpen("No name",
1531 "wm",
60715047 1532 (thandle_t) &ctx,
6d5c85a2
TC
1533 comp_read,
1534 comp_write,
1535 comp_seek,
1536 comp_close,
1537 sizeproc,
1538 comp_mmap,
1539 comp_munmap);
bd8052a6
TC
1540
1541
1542
1543 if (!tif) {
1544 mm_log((1, "i_writetiff_multi_wiol: Unable to open tif file for writing\n"));
1545 i_push_error(0, "Could not create TIFF object");
1546 TIFFSetErrorHandler(old_handler);
60715047 1547 tiffio_context_final(&ctx);
33ca1a7e 1548 i_mutex_unlock(mutex);
bd8052a6
TC
1549 return 0;
1550 }
1551
1552 for (i = 0; i < count; ++i) {
1553 if (!i_writetiff_low(tif, imgs[i])) {
1554 TIFFClose(tif);
1555 TIFFSetErrorHandler(old_handler);
60715047 1556 tiffio_context_final(&ctx);
33ca1a7e 1557 i_mutex_unlock(mutex);
bd8052a6
TC
1558 return 0;
1559 }
1560
1561 if (!TIFFWriteDirectory(tif)) {
1562 i_push_error(0, "Cannot write TIFF directory");
1563 TIFFClose(tif);
2691d220 1564 TIFFSetErrorHandler(old_handler);
60715047 1565 tiffio_context_final(&ctx);
33ca1a7e 1566 i_mutex_unlock(mutex);
10461f9a
TC
1567 return 0;
1568 }
1569 }
1570
2691d220 1571 TIFFSetErrorHandler(old_handler);
10461f9a 1572 (void) TIFFClose(tif);
60715047 1573 tiffio_context_final(&ctx);
e482e0b3 1574
33ca1a7e
TC
1575 i_mutex_unlock(mutex);
1576
6d5c85a2
TC
1577 if (i_io_close(ig))
1578 return 0;
1579
10461f9a
TC
1580 return 1;
1581}
1582
1583/*
1584=item i_writetiff_multi_wiol_faxable(ig, imgs, count, fine_mode)
1585
1586Stores an image in the iolayer object.
1587
1588 ig - io_object that defines source to write to
1589 imgs,count - the images to write
1590 fine_mode - select fine or normal mode fax images
1591
1592=cut
1593*/
1594
1595
1596undef_int
1597i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
1598 TIFF* tif;
1599 int i;
2691d220 1600 TIFFErrorHandler old_handler;
60715047 1601 tiffio_context_t ctx;
e482e0b3 1602
33ca1a7e
TC
1603 i_mutex_lock(mutex);
1604
2691d220 1605 old_handler = TIFFSetErrorHandler(error_handler);
d2dfdcc9 1606
10461f9a 1607 i_clear_error();
8d14daab 1608 mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n",
10461f9a 1609 ig, imgs, count));
d2dfdcc9 1610
60715047 1611 tiffio_context_init(&ctx, ig);
d2dfdcc9
TC
1612
1613 tif = TIFFClientOpen("No name",
1614 "wm",
60715047 1615 (thandle_t) &ctx,
6d5c85a2
TC
1616 comp_read,
1617 comp_write,
1618 comp_seek,
1619 comp_close,
1620 sizeproc,
1621 comp_mmap,
1622 comp_munmap);
10461f9a
TC
1623
1624
d2dfdcc9
TC
1625
1626 if (!tif) {
10461f9a 1627 mm_log((1, "i_writetiff_mulit_wiol: Unable to open tif file for writing\n"));
2691d220
TC
1628 i_push_error(0, "Could not create TIFF object");
1629 TIFFSetErrorHandler(old_handler);
60715047 1630 tiffio_context_final(&ctx);
33ca1a7e 1631 i_mutex_unlock(mutex);
d2dfdcc9
TC
1632 return 0;
1633 }
1634
10461f9a
TC
1635 for (i = 0; i < count; ++i) {
1636 if (!i_writetiff_low_faxable(tif, imgs[i], fine)) {
1637 TIFFClose(tif);
2691d220 1638 TIFFSetErrorHandler(old_handler);
60715047 1639 tiffio_context_final(&ctx);
33ca1a7e 1640 i_mutex_unlock(mutex);
10461f9a
TC
1641 return 0;
1642 }
d2dfdcc9 1643
10461f9a
TC
1644 if (!TIFFWriteDirectory(tif)) {
1645 i_push_error(0, "Cannot write TIFF directory");
1646 TIFFClose(tif);
2691d220 1647 TIFFSetErrorHandler(old_handler);
60715047 1648 tiffio_context_final(&ctx);
33ca1a7e 1649 i_mutex_unlock(mutex);
10461f9a
TC
1650 return 0;
1651 }
1652 }
d2dfdcc9 1653
10461f9a 1654 (void) TIFFClose(tif);
2691d220 1655 TIFFSetErrorHandler(old_handler);
60715047 1656 tiffio_context_final(&ctx);
e482e0b3 1657
33ca1a7e
TC
1658 i_mutex_unlock(mutex);
1659
6d5c85a2
TC
1660 if (i_io_close(ig))
1661 return 0;
1662
10461f9a
TC
1663 return 1;
1664}
d2dfdcc9 1665
10461f9a
TC
1666/*
1667=item i_writetiff_wiol(im, ig)
d2dfdcc9 1668
10461f9a
TC
1669Stores an image in the iolayer object.
1670
1671 im - image object to write out
1672 ig - io_object that defines source to write to
1673
1674=cut
1675*/
1676undef_int
1677i_writetiff_wiol(i_img *img, io_glue *ig) {
1678 TIFF* tif;
2691d220 1679 TIFFErrorHandler old_handler;
60715047 1680 tiffio_context_t ctx;
e482e0b3 1681
33ca1a7e
TC
1682 i_mutex_lock(mutex);
1683
2691d220 1684 old_handler = TIFFSetErrorHandler(error_handler);
10461f9a 1685
10461f9a 1686 i_clear_error();
8d14daab 1687 mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", img, ig));
10461f9a 1688
60715047 1689 tiffio_context_init(&ctx, ig);
2691d220 1690
10461f9a
TC
1691 tif = TIFFClientOpen("No name",
1692 "wm",
60715047 1693 (thandle_t) &ctx,
6d5c85a2
TC
1694 comp_read,
1695 comp_write,
1696 comp_seek,
1697 comp_close,
1698 sizeproc,
1699 comp_mmap,
1700 comp_munmap);
10461f9a
TC
1701
1702
1703
1704 if (!tif) {
1705 mm_log((1, "i_writetiff_wiol: Unable to open tif file for writing\n"));
2691d220 1706 i_push_error(0, "Could not create TIFF object");
60715047 1707 tiffio_context_final(&ctx);
2691d220 1708 TIFFSetErrorHandler(old_handler);
33ca1a7e 1709 i_mutex_unlock(mutex);
10461f9a 1710 return 0;
d2dfdcc9 1711 }
d2dfdcc9 1712
10461f9a 1713 if (!i_writetiff_low(tif, img)) {
fd9a31d2 1714 TIFFClose(tif);
60715047 1715 tiffio_context_final(&ctx);
2691d220 1716 TIFFSetErrorHandler(old_handler);
33ca1a7e 1717 i_mutex_unlock(mutex);
fd9a31d2
TC
1718 return 0;
1719 }
1720
10461f9a 1721 (void) TIFFClose(tif);
2691d220 1722 TIFFSetErrorHandler(old_handler);
33ca1a7e
TC
1723 tiffio_context_final(&ctx);
1724 i_mutex_unlock(mutex);
2691d220 1725
6d5c85a2
TC
1726 if (i_io_close(ig))
1727 return 0;
1728
10461f9a
TC
1729 return 1;
1730}
1731
1732
1733
1734/*
1735=item i_writetiff_wiol_faxable(i_img *, io_glue *)
1736
1737Stores an image in the iolayer object in faxable tiff format.
1738
1739 im - image object to write out
1740 ig - io_object that defines source to write to
1741
1742Note, this may be rewritten to use to simply be a call to a
1743lower-level function that gives more options for writing tiff at some
1744point.
1745
1746=cut
1747*/
1748
1749undef_int
1750i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine) {
1751 TIFF* tif;
2691d220 1752 TIFFErrorHandler old_handler;
60715047 1753 tiffio_context_t ctx;
e482e0b3 1754
33ca1a7e
TC
1755 i_mutex_lock(mutex);
1756
2691d220 1757 old_handler = TIFFSetErrorHandler(error_handler);
10461f9a 1758
10461f9a 1759 i_clear_error();
8d14daab 1760 mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", im, ig));
10461f9a 1761
60715047 1762 tiffio_context_init(&ctx, ig);
10461f9a
TC
1763
1764 tif = TIFFClientOpen("No name",
1765 "wm",
60715047 1766 (thandle_t) &ctx,
6d5c85a2
TC
1767 comp_read,
1768 comp_write,
1769 comp_seek,
1770 comp_close,
1771 sizeproc,
1772 comp_mmap,
1773 comp_munmap);
10461f9a
TC
1774
1775
1776
1777 if (!tif) {
1778 mm_log((1, "i_writetiff_wiol: Unable to open tif file for writing\n"));
2691d220
TC
1779 i_push_error(0, "Could not create TIFF object");
1780 TIFFSetErrorHandler(old_handler);
60715047 1781 tiffio_context_final(&ctx);
33ca1a7e 1782 i_mutex_unlock(mutex);
10461f9a 1783 return 0;
d2dfdcc9 1784 }
10461f9a
TC
1785
1786 if (!i_writetiff_low_faxable(tif, im, fine)) {
1787 TIFFClose(tif);
2691d220 1788 TIFFSetErrorHandler(old_handler);
60715047 1789 tiffio_context_final(&ctx);
33ca1a7e 1790 i_mutex_unlock(mutex);
10461f9a
TC
1791 return 0;
1792 }
1793
d2dfdcc9 1794 (void) TIFFClose(tif);
2691d220 1795 TIFFSetErrorHandler(old_handler);
60715047 1796 tiffio_context_final(&ctx);
33ca1a7e 1797 i_mutex_unlock(mutex);
2691d220 1798
6d5c85a2
TC
1799 if (i_io_close(ig))
1800 return 0;
1801
d2dfdcc9
TC
1802 return 1;
1803}
1804
fd9a31d2
TC
1805static int save_tiff_tags(TIFF *tif, i_img *im) {
1806 int i;
10461f9a 1807
fd9a31d2
TC
1808 for (i = 0; i < text_tag_count; ++i) {
1809 int entry;
1810 if (i_tags_find(&im->tags, text_tag_names[i].name, 0, &entry)) {
1811 if (!TIFFSetField(tif, text_tag_names[i].tag,
10461f9a
TC
1812 im->tags.tags[entry].data)) {
1813 i_push_errorf(0, "cannot save %s to TIFF", text_tag_names[i].name);
1814 return 0;
fd9a31d2
TC
1815 }
1816 }
1817 }
60715047 1818
fd9a31d2
TC
1819 return 1;
1820}
b8c2033e 1821
10461f9a 1822
bd8052a6
TC
1823static void
1824unpack_4bit_to(unsigned char *dest, const unsigned char *src,
8d14daab 1825 size_t src_byte_count) {
bd8052a6
TC
1826 while (src_byte_count > 0) {
1827 *dest++ = *src >> 4;
1828 *dest++ = *src++ & 0xf;
1829 --src_byte_count;
1830 }
1831}
5bb828f1 1832
bd8052a6 1833static void pack_4bit_to(unsigned char *dest, const unsigned char *src,
8d14daab 1834 i_img_dim pixel_count) {
bd8052a6
TC
1835 int i = 0;
1836 while (i < pixel_count) {
1837 if ((i & 1) == 0) {
1838 *dest = *src++ << 4;
1839 }
1840 else {
1841 *dest++ |= *src++;
1842 }
1843 ++i;
1844 }
1845}
5bb828f1 1846
6b7197d0
TC
1847/*
1848=item fallback_rgb_channels
1849
1850Calculate the number of output channels when we fallback to the RGBA
1851family of functions.
1852
1853=cut
1854*/
1855
1856static void
1857fallback_rgb_channels(TIFF *tif, i_img_dim width, i_img_dim height, int *channels, int *alpha_chan) {
bd8052a6 1858 uint16 photometric;
6b7197d0 1859 uint16 in_channels;
bd8052a6
TC
1860 uint16 extra_count;
1861 uint16 *extras;
5bb828f1 1862
bd8052a6
TC
1863 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &in_channels);
1864 TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
5bb828f1 1865
bd8052a6
TC
1866 switch (photometric) {
1867 case PHOTOMETRIC_SEPARATED:
6b7197d0 1868 *channels = 3;
bd8052a6
TC
1869 break;
1870
1871 case PHOTOMETRIC_MINISWHITE:
1872 case PHOTOMETRIC_MINISBLACK:
1873 /* the TIFF RGBA functions expand single channel grey into RGB,
1874 so reduce it, we move the alpha channel into the right place
1875 if needed */
6b7197d0 1876 *channels = 1;
bd8052a6 1877 break;
5bb828f1 1878
bd8052a6 1879 default:
6b7197d0 1880 *channels = 3;
bd8052a6
TC
1881 break;
1882 }
1883 /* TIFF images can have more than one alpha channel, but Imager can't
1884 this ignores the possibility of 2 channel images with 2 alpha,
1885 but there's not much I can do about that */
1886 *alpha_chan = 0;
1887 if (TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)
1888 && extra_count) {
6b7197d0 1889 *alpha_chan = (*channels)++;
5bb828f1 1890 }
6b7197d0
TC
1891}
1892
1893static i_img *
1894make_rgb(TIFF *tif, i_img_dim width, i_img_dim height, int *alpha_chan) {
1895 int channels = 0;
1896
1897 fallback_rgb_channels(tif, width, height, &channels, alpha_chan);
bd8052a6
TC
1898
1899 return i_img_8_new(width, height, channels);
5bb828f1
TC
1900}
1901
bd8052a6 1902static i_img *
8d14daab 1903read_one_rgb_lines(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete) {
bd8052a6
TC
1904 i_img *im;
1905 uint32* raster = NULL;
1906 uint32 rowsperstrip, row;
1907 i_color *line_buf;
1908 int alpha_chan;
694d935c 1909 int rc;
bd8052a6
TC
1910
1911 im = make_rgb(tif, width, height, &alpha_chan);
1912 if (!im)
1913 return NULL;
1914
694d935c 1915 rc = TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
bd8052a6
TC
1916 mm_log((1, "i_readtiff_wiol: rowsperstrip=%d rc = %d\n", rowsperstrip, rc));
1917
1918 if (rc != 1 || rowsperstrip==-1) {
1919 rowsperstrip = height;
1920 }
1921
1922 raster = (uint32*)_TIFFmalloc(width * rowsperstrip * sizeof (uint32));
1923 if (!raster) {
1924 i_img_destroy(im);
1925 i_push_error(0, "No space for raster buffer");
1926 return NULL;
1927 }
1928
1929 line_buf = mymalloc(sizeof(i_color) * width);
1930
1931 for( row = 0; row < height; row += rowsperstrip ) {
1932 uint32 newrows, i_row;
1933
1934 if (!TIFFReadRGBAStrip(tif, row, raster)) {
1935 if (allow_incomplete) {
1936 i_tags_setn(&im->tags, "i_lines_read", row);
1937 i_tags_setn(&im->tags, "i_incomplete", 1);
1938 break;
1939 }
1940 else {
1941 i_push_error(0, "could not read TIFF image strip");
1942 _TIFFfree(raster);
1943 i_img_destroy(im);
1944 return NULL;
1945 }
1946 }
1947
1948 newrows = (row+rowsperstrip > height) ? height-row : rowsperstrip;
1949 mm_log((1, "newrows=%d\n", newrows));
1950
1951 for( i_row = 0; i_row < newrows; i_row++ ) {
1952 uint32 x;
1953 i_color *outp = line_buf;
1954
1955 for(x = 0; x<width; x++) {
1956 uint32 temp = raster[x+width*(newrows-i_row-1)];
1957 outp->rgba.r = TIFFGetR(temp);
1958 outp->rgba.g = TIFFGetG(temp);
1959 outp->rgba.b = TIFFGetB(temp);
1960
1961 if (alpha_chan) {
1962 /* the libtiff RGBA code expands greyscale into RGBA, so put the
1963 alpha in the right place and scale it */
1964 int ch;
1965 outp->channel[alpha_chan] = TIFFGetA(temp);
1966 if (outp->channel[alpha_chan]) {
1967 for (ch = 0; ch < alpha_chan; ++ch) {
1968 outp->channel[ch] = outp->channel[ch] * 255 / outp->channel[alpha_chan];
1969 }
1970 }
1971 }
1972
1973 outp++;
1974 }
1975 i_plin(im, 0, width, i_row+row, line_buf);
1976 }
f62b2d84 1977 }
bd8052a6
TC
1978
1979 myfree(line_buf);
1980 _TIFFfree(raster);
1981
1982 return im;
1983}
1984
1985/* adapted from libtiff
1986
1987 libtiff's TIFFReadRGBATile succeeds even when asked to read an
1988 invalid tile, which means we have no way of knowing whether the data
1989 we received from it is valid or not.
1990
1991 So the caller here has set stoponerror to 1 so that
1992 TIFFRGBAImageGet() will fail.
1993
1994 read_one_rgb_tiled() then takes that into account for i_incomplete
1995 or failure.
1996 */
1997static int
1998myTIFFReadRGBATile(TIFFRGBAImage *img, uint32 col, uint32 row, uint32 * raster)
1999
2000{
2001 int ok;
2002 uint32 tile_xsize, tile_ysize;
2003 uint32 read_xsize, read_ysize;
2004 uint32 i_row;
2005
2006 /*
2007 * Verify that our request is legal - on a tile file, and on a
2008 * tile boundary.
2009 */
2010
2011 TIFFGetFieldDefaulted(img->tif, TIFFTAG_TILEWIDTH, &tile_xsize);
2012 TIFFGetFieldDefaulted(img->tif, TIFFTAG_TILELENGTH, &tile_ysize);
2013 if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 )
2014 {
2015 i_push_errorf(0, "Row/col passed to myTIFFReadRGBATile() must be top"
2016 "left corner of a tile.");
2017 return 0;
2018 }
2019
2020 /*
2021 * The TIFFRGBAImageGet() function doesn't allow us to get off the
2022 * edge of the image, even to fill an otherwise valid tile. So we
2023 * figure out how much we can read, and fix up the tile buffer to
2024 * a full tile configuration afterwards.
2025 */
2026
2027 if( row + tile_ysize > img->height )
2028 read_ysize = img->height - row;
2029 else
2030 read_ysize = tile_ysize;
2031
2032 if( col + tile_xsize > img->width )
2033 read_xsize = img->width - col;
2034 else
2035 read_xsize = tile_xsize;
2036
2037 /*
2038 * Read the chunk of imagery.
2039 */
2040
2041 img->row_offset = row;
2042 img->col_offset = col;
2043
2044 ok = TIFFRGBAImageGet(img, raster, read_xsize, read_ysize );
2045
2046 /*
2047 * If our read was incomplete we will need to fix up the tile by
2048 * shifting the data around as if a full tile of data is being returned.
2049 *
2050 * This is all the more complicated because the image is organized in
2051 * bottom to top format.
2052 */
2053
2054 if( read_xsize == tile_xsize && read_ysize == tile_ysize )
2055 return( ok );
2056
2057 for( i_row = 0; i_row < read_ysize; i_row++ ) {
2058 memmove( raster + (tile_ysize - i_row - 1) * tile_xsize,
2059 raster + (read_ysize - i_row - 1) * read_xsize,
2060 read_xsize * sizeof(uint32) );
2061 _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize,
2062 0, sizeof(uint32) * (tile_xsize - read_xsize) );
2063 }
2064
2065 for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) {
2066 _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize,
2067 0, sizeof(uint32) * tile_xsize );
2068 }
2069
2070 return (ok);
f62b2d84 2071}
5bb828f1 2072
bd8052a6 2073static i_img *
8d14daab 2074read_one_rgb_tiled(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete) {
bd8052a6
TC
2075 i_img *im;
2076 uint32* raster = NULL;
2077 int ok = 1;
2078 uint32 row, col;
2079 uint32 tile_width, tile_height;
2080 unsigned long pixels = 0;
2081 char emsg[1024] = "";
2082 TIFFRGBAImage img;
2083 i_color *line;
2084 int alpha_chan;
2085
2086 im = make_rgb(tif, width, height, &alpha_chan);
2087 if (!im)
2088 return NULL;
2089
2090 if (!TIFFRGBAImageOK(tif, emsg)
2091 || !TIFFRGBAImageBegin(&img, tif, 1, emsg)) {
2092 i_push_error(0, emsg);
2093 i_img_destroy(im);
2094 return( 0 );
2095 }
2096
2097 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width);
2098 TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height);
2099 mm_log((1, "i_readtiff_wiol: tile_width=%d, tile_height=%d\n", tile_width, tile_height));
2100
2101 raster = (uint32*)_TIFFmalloc(tile_width * tile_height * sizeof (uint32));
2102 if (!raster) {
2103 i_img_destroy(im);
2104 i_push_error(0, "No space for raster buffer");
2105 TIFFRGBAImageEnd(&img);
2106 return NULL;
2107 }
2108 line = mymalloc(tile_width * sizeof(i_color));
2109
2110 for( row = 0; row < height; row += tile_height ) {
2111 for( col = 0; col < width; col += tile_width ) {
2112
2113 /* Read the tile into an RGBA array */
2114 if (myTIFFReadRGBATile(&img, col, row, raster)) {
2115 uint32 i_row, x;
2116 uint32 newrows = (row+tile_height > height) ? height-row : tile_height;
2117 uint32 newcols = (col+tile_width > width ) ? width-col : tile_width;
2118
2119 mm_log((1, "i_readtiff_wiol: tile(%d, %d) newcols=%d newrows=%d\n", col, row, newcols, newrows));
2120 for( i_row = 0; i_row < newrows; i_row++ ) {
2121 i_color *outp = line;
2122 for(x = 0; x < newcols; x++) {
2123 uint32 temp = raster[x+tile_width*(tile_height-i_row-1)];
2124 outp->rgba.r = TIFFGetR(temp);
2125 outp->rgba.g = TIFFGetG(temp);
2126 outp->rgba.b = TIFFGetB(temp);
2127 outp->rgba.a = TIFFGetA(temp);
2128
2129 if (alpha_chan) {
2130 /* the libtiff RGBA code expands greyscale into RGBA, so put the
2131 alpha in the right place and scale it */
2132 int ch;
2133 outp->channel[alpha_chan] = TIFFGetA(temp);
2134
2135 if (outp->channel[alpha_chan]) {
2136 for (ch = 0; ch < alpha_chan; ++ch) {
2137 outp->channel[ch] = outp->channel[ch] * 255 / outp->channel[alpha_chan];
2138 }
2139 }
2140 }
2141
2142 ++outp;
2143 }
2144 i_plin(im, col, col+newcols, row+i_row, line);
2145 }
2146 pixels += newrows * newcols;
2147 }
2148 else {
2149 if (allow_incomplete) {
2150 ok = 0;
2151 }
2152 else {
2153 goto error;
2154 }
2155 }
2156 }
2157 }
2158
2159 if (!ok) {
2160 if (pixels == 0) {
2161 i_push_error(0, "TIFF: No image data could be read from the image");
2162 goto error;
2163 }
2164
2165 /* incomplete image */
2166 i_tags_setn(&im->tags, "i_incomplete", 1);
2167 i_tags_setn(&im->tags, "i_lines_read", pixels / width);
2168 }
2169
2170 myfree(line);
2171 TIFFRGBAImageEnd(&img);
2172 _TIFFfree(raster);
2173
2174 return im;
2175
2176 error:
2177 myfree(line);
2178 _TIFFfree(raster);
2179 TIFFRGBAImageEnd(&img);
2180 i_img_destroy(im);
2181 return NULL;
2182}
2183
2184char const *
2185i_tiff_libversion(void) {
2186 return TIFFGetVersion();
2187}
2188
2189static int
2190setup_paletted(read_state_t *state) {
2191 uint16 *maps[3];
2192 int i, ch;
2193 int color_count = 1 << state->bits_per_sample;
2194
2195 state->img = i_img_pal_new(state->width, state->height, 3, 256);
2196 if (!state->img)
2197 return 0;
2198
2199 /* setup the color map */
2200 if (!TIFFGetField(state->tif, TIFFTAG_COLORMAP, maps+0, maps+1, maps+2)) {
2201 i_push_error(0, "Cannot get colormap for paletted image");
2202 i_img_destroy(state->img);
2203 return 0;
2204 }
2205 for (i = 0; i < color_count; ++i) {
2206 i_color c;
2207 for (ch = 0; ch < 3; ++ch) {
2208 c.channel[ch] = Sample16To8(maps[ch][i]);
2209 }
2210 i_addcolors(state->img, &c, 1);
2211 }
2212
2213 return 1;
2214}
2215
2216static int
2217tile_contig_getter(read_state_t *state, read_putter_t putter) {
2218 uint32 tile_width, tile_height;
2219 uint32 this_tile_height, this_tile_width;
2220 uint32 rows_left, cols_left;
2221 uint32 x, y;
2222
2223 state->raster = _TIFFmalloc(TIFFTileSize(state->tif));
2224 if (!state->raster) {
2225 i_push_error(0, "tiff: Out of memory allocating tile buffer");
2226 return 0;
2227 }
2228
2229 TIFFGetField(state->tif, TIFFTAG_TILEWIDTH, &tile_width);
2230 TIFFGetField(state->tif, TIFFTAG_TILELENGTH, &tile_height);
2231 rows_left = state->height;
2232 for (y = 0; y < state->height; y += this_tile_height) {
2233 this_tile_height = rows_left > tile_height ? tile_height : rows_left;
2234
2235 cols_left = state->width;
2236 for (x = 0; x < state->width; x += this_tile_width) {
2237 this_tile_width = cols_left > tile_width ? tile_width : cols_left;
2238
2239 if (TIFFReadTile(state->tif,
2240 state->raster,
2241 x, y, 0, 0) < 0) {
2242 if (!state->allow_incomplete) {
2243 return 0;
2244 }
2245 }
2246 else {
2247 putter(state, x, y, this_tile_width, this_tile_height, tile_width - this_tile_width);
2248 }
2249
2250 cols_left -= this_tile_width;
2251 }
2252
2253 rows_left -= this_tile_height;
2254 }
2255
2256 return 1;
2257}
2258
2259static int
2260strip_contig_getter(read_state_t *state, read_putter_t putter) {
2261 uint32 rows_per_strip;
2262 tsize_t strip_size = TIFFStripSize(state->tif);
2263 uint32 y, strip_rows, rows_left;
2264
2265 state->raster = _TIFFmalloc(strip_size);
2266 if (!state->raster) {
2267 i_push_error(0, "tiff: Out of memory allocating strip buffer");
2268 return 0;
2269 }
2270
2271 TIFFGetFieldDefaulted(state->tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
2272 rows_left = state->height;
2273 for (y = 0; y < state->height; y += strip_rows) {
2274 strip_rows = rows_left > rows_per_strip ? rows_per_strip : rows_left;
2275 if (TIFFReadEncodedStrip(state->tif,
2276 TIFFComputeStrip(state->tif, y, 0),
2277 state->raster,
2278 strip_size) < 0) {
2279 if (!state->allow_incomplete)
2280 return 0;
2281 }
2282 else {
2283 putter(state, 0, y, state->width, strip_rows, 0);
2284 }
2285 rows_left -= strip_rows;
2286 }
2287
2288 return 1;
2289}
2290
2291static int
8d14daab 2292paletted_putter8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, int extras) {
bd8052a6
TC
2293 unsigned char *p = state->raster;
2294
8d14daab 2295 state->pixels_read += width * height;
bd8052a6
TC
2296 while (height > 0) {
2297 i_ppal(state->img, x, x + width, y, p);
2298 p += width + extras;
2299 --height;
2300 ++y;
2301 }
2302
2303 return 1;
2304}
2305
2306static int
8d14daab 2307paletted_putter4(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, int extras) {
bd8052a6
TC
2308 uint32 img_line_size = (width + 1) / 2;
2309 uint32 skip_line_size = (width + extras + 1) / 2;
2310 unsigned char *p = state->raster;
2311
2312 if (!state->line_buf)
2313 state->line_buf = mymalloc(state->width);
2314
8d14daab 2315 state->pixels_read += width * height;
bd8052a6
TC
2316 while (height > 0) {
2317 unpack_4bit_to(state->line_buf, p, img_line_size);
2318 i_ppal(state->img, x, x + width, y, state->line_buf);
2319 p += skip_line_size;
2320 --height;
2321 ++y;
2322 }
2323
2324 return 1;
2325}
2326
2327static void
2328rgb_channels(read_state_t *state, int *out_channels) {
2329 uint16 extra_count;
2330 uint16 *extras;
2331
2332 /* safe defaults */
2333 *out_channels = 3;
2334 state->alpha_chan = 0;
2335 state->scale_alpha = 0;
05c9b356 2336 state->color_channels = 3;
bd8052a6
TC
2337
2338 /* plain RGB */
2339 if (state->samples_per_pixel == 3)
2340 return;
2341
2342 if (!TIFFGetField(state->tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)) {
2343 mm_log((1, "tiff: samples != 3 but no extra samples tag\n"));
2344 return;
2345 }
2346
2347 if (!extra_count) {
2348 mm_log((1, "tiff: samples != 3 but no extra samples listed"));
2349 return;
2350 }
2351
2352 ++*out_channels;
2353 state->alpha_chan = 3;
2354 switch (*extras) {
2355 case EXTRASAMPLE_UNSPECIFIED:
2356 case EXTRASAMPLE_ASSOCALPHA:
2357 state->scale_alpha = 1;
2358 break;
2359
2360 case EXTRASAMPLE_UNASSALPHA:
2361 state->scale_alpha = 0;
2362 break;
2363
2364 default:
2365 mm_log((1, "tiff: unknown extra sample type %d, treating as assoc alpha\n",
2366 *extras));
2367 state->scale_alpha = 1;
2368 break;
2369 }
2370 mm_log((1, "tiff alpha channel %d scale %d\n", state->alpha_chan, state->scale_alpha));
2371}
2372
2373static void
2374grey_channels(read_state_t *state, int *out_channels) {
2375 uint16 extra_count;
2376 uint16 *extras;
2377
2378 /* safe defaults */
2379 *out_channels = 1;
2380 state->alpha_chan = 0;
2381 state->scale_alpha = 0;
05c9b356 2382 state->color_channels = 1;
bd8052a6
TC
2383
2384 /* plain grey */
2385 if (state->samples_per_pixel == 1)
2386 return;
2387
2388 if (!TIFFGetField(state->tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)) {
2389 mm_log((1, "tiff: samples != 1 but no extra samples tag\n"));
2390 return;
2391 }
2392
2393 if (!extra_count) {
2394 mm_log((1, "tiff: samples != 1 but no extra samples listed"));
2395 return;
2396 }
2397
2398 ++*out_channels;
2399 state->alpha_chan = 1;
2400 switch (*extras) {
2401 case EXTRASAMPLE_UNSPECIFIED:
2402 case EXTRASAMPLE_ASSOCALPHA:
2403 state->scale_alpha = 1;
2404 break;
2405
2406 case EXTRASAMPLE_UNASSALPHA:
2407 state->scale_alpha = 0;
2408 break;
2409
2410 default:
2411 mm_log((1, "tiff: unknown extra sample type %d, treating as assoc alpha\n",
2412 *extras));
2413 state->scale_alpha = 1;
2414 break;
2415 }
2416}
2417
2418static int
2419setup_16_rgb(read_state_t *state) {
2420 int out_channels;
2421
2422 rgb_channels(state, &out_channels);
2423
2424 state->img = i_img_16_new(state->width, state->height, out_channels);
2425 if (!state->img)
2426 return 0;
2427 state->line_buf = mymalloc(sizeof(unsigned) * state->width * out_channels);
2428
2429 return 1;
2430}
2431
2432static int
2433setup_16_grey(read_state_t *state) {
2434 int out_channels;
2435
2436 grey_channels(state, &out_channels);
2437
2438 state->img = i_img_16_new(state->width, state->height, out_channels);
2439 if (!state->img)
2440 return 0;
2441 state->line_buf = mymalloc(sizeof(unsigned) * state->width * out_channels);
2442
2443 return 1;
2444}
2445
2446static int
8d14daab 2447putter_16(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
bd8052a6
TC
2448 int row_extras) {
2449 uint16 *p = state->raster;
2450 int out_chan = state->img->channels;
2451
8d14daab 2452 state->pixels_read += width * height;
bd8052a6 2453 while (height > 0) {
8d14daab 2454 i_img_dim i;
bd8052a6
TC
2455 int ch;
2456 unsigned *outp = state->line_buf;
2457
2458 for (i = 0; i < width; ++i) {
2459 for (ch = 0; ch < out_chan; ++ch) {
2460 outp[ch] = p[ch];
2461 }
05c9b356
TC
2462 if (state->sample_signed) {
2463 for (ch = 0; ch < state->color_channels; ++ch)
2464 outp[ch] ^= 0x8000;
2465 }
bd8052a6
TC
2466 if (state->alpha_chan && state->scale_alpha && outp[state->alpha_chan]) {
2467 for (ch = 0; ch < state->alpha_chan; ++ch) {
2468 int result = 0.5 + (outp[ch] * 65535.0 / outp[state->alpha_chan]);
2469 outp[ch] = CLAMP16(result);
2470 }
2471 }
2472 p += state->samples_per_pixel;
2473 outp += out_chan;
2474 }
2475
2476 i_psamp_bits(state->img, x, x + width, y, state->line_buf, NULL, out_chan, 16);
2477
2478 p += row_extras * state->samples_per_pixel;
2479 --height;
2480 ++y;
2481 }
2482
2483 return 1;
2484}
2485
2486static int
2487setup_8_rgb(read_state_t *state) {
2488 int out_channels;
2489
2490 rgb_channels(state, &out_channels);
2491
2492 state->img = i_img_8_new(state->width, state->height, out_channels);
2493 if (!state->img)
2494 return 0;
2495 state->line_buf = mymalloc(sizeof(unsigned) * state->width * out_channels);
2496
2497 return 1;
2498}
2499
2500static int
2501setup_8_grey(read_state_t *state) {
2502 int out_channels;
2503
2504 grey_channels(state, &out_channels);
2505
2506 state->img = i_img_8_new(state->width, state->height, out_channels);
2507 if (!state->img)
2508 return 0;
2509 state->line_buf = mymalloc(sizeof(i_color) * state->width * out_channels);
2510
2511 return 1;
2512}
2513
2514static int
8d14daab 2515putter_8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
bd8052a6
TC
2516 int row_extras) {
2517 unsigned char *p = state->raster;
2518 int out_chan = state->img->channels;
2519
8d14daab 2520 state->pixels_read += width * height;
bd8052a6 2521 while (height > 0) {
8d14daab 2522 i_img_dim i;
bd8052a6
TC
2523 int ch;
2524 i_color *outp = state->line_buf;
2525
2526 for (i = 0; i < width; ++i) {
2527 for (ch = 0; ch < out_chan; ++ch) {
2528 outp->channel[ch] = p[ch];
2529 }
05c9b356
TC
2530 if (state->sample_signed) {
2531 for (ch = 0; ch < state->color_channels; ++ch)
2532 outp->channel[ch] ^= 0x80;
2533 }
bd8052a6
TC
2534 if (state->alpha_chan && state->scale_alpha
2535 && outp->channel[state->alpha_chan]) {
2536 for (ch = 0; ch < state->alpha_chan; ++ch) {
2537 int result = (outp->channel[ch] * 255 + 127) / outp->channel[state->alpha_chan];
2538
2539 outp->channel[ch] = CLAMP8(result);
2540 }
2541 }
2542 p += state->samples_per_pixel;
2543 outp++;
2544 }
2545
2546 i_plin(state->img, x, x + width, y, state->line_buf);
2547
2548 p += row_extras * state->samples_per_pixel;
2549 --height;
2550 ++y;
2551 }
2552
2553 return 1;
2554}
2555
2556static int
2557setup_32_rgb(read_state_t *state) {
2558 int out_channels;
2559
2560 rgb_channels(state, &out_channels);
2561
2562 state->img = i_img_double_new(state->width, state->height, out_channels);
2563 if (!state->img)
2564 return 0;
2565 state->line_buf = mymalloc(sizeof(i_fcolor) * state->width);
2566
2567 return 1;
2568}
2569
2570static int
2571setup_32_grey(read_state_t *state) {
2572 int out_channels;
2573
2574 grey_channels(state, &out_channels);
2575
2576 state->img = i_img_double_new(state->width, state->height, out_channels);
2577 if (!state->img)
2578 return 0;
2579 state->line_buf = mymalloc(sizeof(i_fcolor) * state->width);
2580
2581 return 1;
2582}
2583
2584static int
8d14daab 2585putter_32(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
bd8052a6
TC
2586 int row_extras) {
2587 uint32 *p = state->raster;
2588 int out_chan = state->img->channels;
2589
8d14daab 2590 state->pixels_read += width * height;
bd8052a6 2591 while (height > 0) {
8d14daab 2592 i_img_dim i;
bd8052a6
TC
2593 int ch;
2594 i_fcolor *outp = state->line_buf;
2595
2596 for (i = 0; i < width; ++i) {
05c9b356
TC
2597#ifdef IEEEFP_TYPES
2598 if (state->sample_format == SAMPLEFORMAT_IEEEFP) {
2599 const float *pv = (const float *)p;
2600 for (ch = 0; ch < out_chan; ++ch) {
2601 outp->channel[ch] = pv[ch];
2602 }
2603 }
2604 else {
2605#endif
2606 for (ch = 0; ch < out_chan; ++ch) {
2607 if (state->sample_signed && ch < state->color_channels)
2608 outp->channel[ch] = (p[ch] ^ 0x80000000UL) / 4294967295.0;
2609 else
2610 outp->channel[ch] = p[ch] / 4294967295.0;
2611 }
2612#ifdef IEEEFP_TYPES
bd8052a6 2613 }
05c9b356
TC
2614#endif
2615
bd8052a6
TC
2616 if (state->alpha_chan && state->scale_alpha && outp->channel[state->alpha_chan]) {
2617 for (ch = 0; ch < state->alpha_chan; ++ch)
2618 outp->channel[ch] /= outp->channel[state->alpha_chan];
2619 }
2620 p += state->samples_per_pixel;
2621 outp++;
2622 }
2623
2624 i_plinf(state->img, x, x + width, y, state->line_buf);
2625
2626 p += row_extras * state->samples_per_pixel;
2627 --height;
2628 ++y;
2629 }
2630
2631 return 1;
2632}
2633
2634static int
2635setup_bilevel(read_state_t *state) {
2636 i_color black, white;
2637 state->img = i_img_pal_new(state->width, state->height, 1, 256);
2638 if (!state->img)
2639 return 0;
2640 black.channel[0] = black.channel[1] = black.channel[2] =
2641 black.channel[3] = 0;
2642 white.channel[0] = white.channel[1] = white.channel[2] =
2643 white.channel[3] = 255;
2644 if (state->photometric == PHOTOMETRIC_MINISBLACK) {
2645 i_addcolors(state->img, &black, 1);
2646 i_addcolors(state->img, &white, 1);
2647 }
2648 else {
2649 i_addcolors(state->img, &white, 1);
2650 i_addcolors(state->img, &black, 1);
2651 }
2652 state->line_buf = mymalloc(state->width);
2653
2654 return 1;
2655}
2656
2657static int
8d14daab 2658putter_bilevel(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
bd8052a6
TC
2659 int row_extras) {
2660 unsigned char *line_in = state->raster;
2661 size_t line_size = (width + row_extras + 7) / 8;
2662
2663 /* tifflib returns the bits in MSB2LSB order even when the file is
2664 in LSB2MSB, so we only need to handle MSB2LSB */
8d14daab 2665 state->pixels_read += width * height;
bd8052a6 2666 while (height > 0) {
8d14daab 2667 i_img_dim i;
bd8052a6
TC
2668 unsigned char *outp = state->line_buf;
2669 unsigned char *inp = line_in;
2670 unsigned mask = 0x80;
2671
2672 for (i = 0; i < width; ++i) {
2673 *outp++ = *inp & mask ? 1 : 0;
2674 mask >>= 1;
2675 if (!mask) {
2676 ++inp;
2677 mask = 0x80;
2678 }
2679 }
2680
2681 i_ppal(state->img, x, x + width, y, state->line_buf);
2682
2683 line_in += line_size;
2684 --height;
2685 ++y;
2686 }
2687
2688 return 1;
2689}
2690
2691static void
2692cmyk_channels(read_state_t *state, int *out_channels) {
2693 uint16 extra_count;
2694 uint16 *extras;
2695
2696 /* safe defaults */
2697 *out_channels = 3;
2698 state->alpha_chan = 0;
2699 state->scale_alpha = 0;
05c9b356 2700 state->color_channels = 3;
bd8052a6
TC
2701
2702 /* plain CMYK */
2703 if (state->samples_per_pixel == 4)
2704 return;
2705
2706 if (!TIFFGetField(state->tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)) {
2707 mm_log((1, "tiff: CMYK samples != 4 but no extra samples tag\n"));
2708 return;
2709 }
2710
2711 if (!extra_count) {
2712 mm_log((1, "tiff: CMYK samples != 4 but no extra samples listed"));
2713 return;
2714 }
2715
2716 ++*out_channels;
2717 state->alpha_chan = 4;
2718 switch (*extras) {
2719 case EXTRASAMPLE_UNSPECIFIED:
2720 case EXTRASAMPLE_ASSOCALPHA:
2721 state->scale_alpha = 1;
2722 break;
2723
2724 case EXTRASAMPLE_UNASSALPHA:
2725 state->scale_alpha = 0;
2726 break;
2727
2728 default:
2729 mm_log((1, "tiff: unknown extra sample type %d, treating as assoc alpha\n",
2730 *extras));
2731 state->scale_alpha = 1;
2732 break;
2733 }
2734}
2735
2736static int
2737setup_cmyk8(read_state_t *state) {
2738 int channels;
2739
2740 cmyk_channels(state, &channels);
2741 state->img = i_img_8_new(state->width, state->height, channels);
2742
2743 state->line_buf = mymalloc(sizeof(i_color) * state->width);
2744
2745 return 1;
2746}
2747
2748static int
8d14daab 2749putter_cmyk8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
bd8052a6
TC
2750 int row_extras) {
2751 unsigned char *p = state->raster;
2752
8d14daab 2753 state->pixels_read += width * height;
bd8052a6 2754 while (height > 0) {
8d14daab 2755 i_img_dim i;
bd8052a6
TC
2756 int ch;
2757 i_color *outp = state->line_buf;
2758
2759 for (i = 0; i < width; ++i) {
2760 unsigned char c, m, y, k;
2761 c = p[0];
2762 m = p[1];
2763 y = p[2];
2764 k = 255 - p[3];
05c9b356
TC
2765 if (state->sample_signed) {
2766 c ^= 0x80;
2767 m ^= 0x80;
2768 y ^= 0x80;
2769 k ^= 0x80;
2770 }
bd8052a6
TC
2771 outp->rgba.r = (k * (255 - c)) / 255;
2772 outp->rgba.g = (k * (255 - m)) / 255;
2773 outp->rgba.b = (k * (255 - y)) / 255;
2774 if (state->alpha_chan) {
2775 outp->rgba.a = p[state->alpha_chan];
2776 if (state->scale_alpha
2777 && outp->rgba.a) {
2778 for (ch = 0; ch < 3; ++ch) {
2779 int result = (outp->channel[ch] * 255 + 127) / outp->rgba.a;
2780 outp->channel[ch] = CLAMP8(result);
2781 }
2782 }
2783 }
2784 p += state->samples_per_pixel;
2785 outp++;
2786 }
2787
2788 i_plin(state->img, x, x + width, y, state->line_buf);
2789
2790 p += row_extras * state->samples_per_pixel;
2791 --height;
2792 ++y;
2793 }
2794
2795 return 1;
2796}
2797
2798static int
2799setup_cmyk16(read_state_t *state) {
2800 int channels;
2801
2802 cmyk_channels(state, &channels);
2803 state->img = i_img_16_new(state->width, state->height, channels);
2804
2805 state->line_buf = mymalloc(sizeof(unsigned) * state->width * channels);
2806
2807 return 1;
2808}
2809
2810static int
8d14daab 2811putter_cmyk16(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height,
bd8052a6
TC
2812 int row_extras) {
2813 uint16 *p = state->raster;
2814 int out_chan = state->img->channels;
2815
5e84d110 2816 mm_log((4, "putter_cmyk16(%p, %" i_DF ", %" i_DF ", %" i_DF
cd496c63
TC
2817 ", %" i_DF ", %d)\n", state, i_DFcp(x, y), i_DFcp(width, height),
2818 row_extras));
bd8052a6 2819
8d14daab 2820 state->pixels_read += width * height;
bd8052a6 2821 while (height > 0) {
8d14daab 2822 i_img_dim i;
bd8052a6
TC
2823 int ch;
2824 unsigned *outp = state->line_buf;
2825
2826 for (i = 0; i < width; ++i) {
2827 unsigned c, m, y, k;
2828 c = p[0];
2829 m = p[1];
2830 y = p[2];
2831 k = 65535 - p[3];
05c9b356
TC
2832 if (state->sample_signed) {
2833 c ^= 0x8000;
2834 m ^= 0x8000;
2835 y ^= 0x8000;
2836 k ^= 0x8000;
2837 }
bd8052a6
TC
2838 outp[0] = (k * (65535U - c)) / 65535U;
2839 outp[1] = (k * (65535U - m)) / 65535U;
2840 outp[2] = (k * (65535U - y)) / 65535U;
2841 if (state->alpha_chan) {
2842 outp[3] = p[state->alpha_chan];
2843 if (state->scale_alpha
2844 && outp[3]) {
2845 for (ch = 0; ch < 3; ++ch) {
2846 int result = (outp[ch] * 65535 + 32767) / outp[3];
2847 outp[3] = CLAMP16(result);
2848 }
2849 }
2850 }
2851 p += state->samples_per_pixel;
2852 outp += out_chan;
2853 }
2854
2855 i_psamp_bits(state->img, x, x + width, y, state->line_buf, NULL, out_chan, 16);
2856
2857 p += row_extras * state->samples_per_pixel;
2858 --height;
2859 ++y;
2860 }
2861
2862 return 1;
2863}
2864
2865/*
2866
2867 Older versions of tifflib we support don't define this, so define it
2868 ourselves.
2869
f8d72f20
TC
2870 If you want this detection to do anything useful, use a newer
2871 release of tifflib.
2872
bd8052a6
TC
2873 */
2874#if TIFFLIB_VERSION < 20031121
2875
f8d72f20
TC
2876int
2877TIFFIsCODECConfigured(uint16 scheme) {
bd8052a6 2878 switch (scheme) {
f8d72f20 2879 /* these schemes are all shipped with tifflib */
bd8052a6 2880 case COMPRESSION_NONE:
bd8052a6 2881 case COMPRESSION_PACKBITS:
bd8052a6
TC
2882 case COMPRESSION_CCITTRLE:
2883 case COMPRESSION_CCITTRLEW:
2884 case COMPRESSION_CCITTFAX3:
2885 case COMPRESSION_CCITTFAX4:
f8d72f20 2886 return 1;
bd8052a6 2887
f8d72f20
TC
2888 /* these require external library support */
2889 default:
bd8052a6 2890 case COMPRESSION_JPEG:
bd8052a6 2891 case COMPRESSION_LZW:
bd8052a6
TC
2892 case COMPRESSION_DEFLATE:
2893 case COMPRESSION_ADOBE_DEFLATE:
bd8052a6
TC
2894 return 0;
2895 }
2896}
2897
2898#endif
2899
f8d72f20
TC
2900static int
2901myTIFFIsCODECConfigured(uint16 scheme) {
2902#if TIFFLIB_VERSION < 20040724
2903 if (scheme == COMPRESSION_LZW)
2904 return 0;
2905#endif
2906
2907 return TIFFIsCODECConfigured(scheme);
2908}
2909
60715047
TC
2910static void
2911tiffio_context_init(tiffio_context_t *c, io_glue *ig) {
2912 c->magic = TIFFIO_MAGIC;
2913 c->ig = ig;
2914#ifdef USE_EXT_WARN_HANDLER
2915 c->warn_buffer = NULL;
2916 c->warn_size = 0;
2917#endif
2918}
2919
2920static void
2921tiffio_context_final(tiffio_context_t *c) {
2922 c->magic = TIFFIO_MAGIC;
2923#ifdef USE_EXT_WARN_HANDLER
2924 if (c->warn_buffer)
2925 myfree(c->warn_buffer);
2926#endif
2927}
2928
b8c2033e
AMH
2929/*
2930=back
2931
2932=head1 AUTHOR
2933
5b480b14 2934Arnar M. Hrafnkelsson <addi@umich.edu>, Tony Cook <tonyc@cpan.org>
b8c2033e
AMH
2935
2936=head1 SEE ALSO
2937
2938Imager(3)
2939
2940=cut
2941*/