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