1 /* tiff loading for GIMP
2  *  -Peter Mattis
3  *
4  * The TIFF loading code has been completely revamped by Nick Lamb
5  * njl195@zepler.org.uk -- 18 May 1998
6  * And it now gains support for tiles (and doubtless a zillion bugs)
7  * njl195@zepler.org.uk -- 12 June 1999
8  * LZW patent fuss continues :(
9  * njl195@zepler.org.uk -- 20 April 2000
10  * The code for this filter is based on "tifftopnm" and "pnmtotiff",
11  *  2 programs that are a part of the netpbm package.
12  * khk@khk.net -- 13 May 2000
13  * Added support for ICCPROFILE tiff tag. If this tag is present in a
14  * TIFF file, then a parasite is created and vice versa.
15  * peter@kirchgessner.net -- 29 Oct 2002
16  * Progress bar only when run interactive
17  * Added support for layer offsets - pablo.dangelo@web.de -- 7 Jan 2004
18  * Honor EXTRASAMPLES tag while loading images with alphachannel
19  * pablo.dangelo@web.de -- 16 Jan 2004
20  */
21 
22 #include "config.h"
23 
24 #include <errno.h>
25 #include <string.h>
26 
27 #include <tiffio.h>
28 
29 #include <libgimp/gimp.h>
30 #include <libgimp/gimpui.h>
31 
32 #include "file-tiff-io.h"
33 
34 
35 typedef struct
36 {
37   GFile         *file;
38   GObject       *stream;
39   GInputStream  *input;
40   GOutputStream *output;
41   gboolean       can_seek;
42 
43   gchar         *buffer;
44   gsize          allocated;
45   gsize          used;
46   gsize          position;
47 } TiffIO;
48 
49 
50 static TIFFExtendProc parent_extender;
51 
52 static void      tiff_io_warning       (const gchar *module,
53                                         const gchar *fmt,
54                                         va_list      ap) G_GNUC_PRINTF (2, 0);
55 static void      tiff_io_error         (const gchar *module,
56                                         const gchar *fmt,
57                                         va_list      ap) G_GNUC_PRINTF (2, 0);
58 static tsize_t   tiff_io_read          (thandle_t    handle,
59                                         tdata_t      buffer,
60                                         tsize_t      size);
61 static tsize_t   tiff_io_write         (thandle_t    handle,
62                                         tdata_t      buffer,
63                                         tsize_t      size);
64 static toff_t    tiff_io_seek          (thandle_t    handle,
65                                         toff_t       offset,
66                                         gint         whence);
67 static gint      tiff_io_close         (thandle_t    handle);
68 static toff_t    tiff_io_get_file_size (thandle_t    handle);
69 static void      register_geotags      (TIFF        *tif);
70 
71 static void
register_geotags(TIFF * tif)72 register_geotags (TIFF *tif)
73 {
74   static gboolean geotifftags_registered = FALSE;
75 
76   if (geotifftags_registered)
77     return;
78 
79   geotifftags_registered = TRUE;
80 
81   TIFFMergeFieldInfo (tif, geotifftags_fieldinfo, (sizeof (geotifftags_fieldinfo) / sizeof (geotifftags_fieldinfo[0])));
82 
83   if (parent_extender)
84     (*parent_extender) (tif);
85 }
86 
87 static TiffIO tiff_io = { 0, };
88 
89 
90 TIFF *
tiff_open(GFile * file,const gchar * mode,GError ** error)91 tiff_open (GFile        *file,
92            const gchar  *mode,
93            GError      **error)
94 {
95   TIFFSetWarningHandler ((TIFFErrorHandler) tiff_io_warning);
96   TIFFSetErrorHandler ((TIFFErrorHandler) tiff_io_error);
97 
98   parent_extender = TIFFSetTagExtender (register_geotags);
99 
100   tiff_io.file = file;
101 
102   if (! strcmp (mode, "r"))
103     {
104       tiff_io.input = G_INPUT_STREAM (g_file_read (file, NULL, error));
105       if (! tiff_io.input)
106         return NULL;
107 
108       tiff_io.stream = G_OBJECT (tiff_io.input);
109     }
110   else if(! strcmp (mode, "w"))
111     {
112       tiff_io.output = G_OUTPUT_STREAM (g_file_replace (file,
113                                                         NULL, FALSE,
114                                                         G_FILE_CREATE_NONE,
115                                                         NULL, error));
116       if (! tiff_io.output)
117         return NULL;
118 
119       tiff_io.stream = G_OBJECT (tiff_io.output);
120     }
121   else if(! strcmp (mode, "a"))
122     {
123       GIOStream *iostream = G_IO_STREAM (g_file_open_readwrite (file, NULL,
124                                                                 error));
125       if (! iostream)
126         return NULL;
127 
128       tiff_io.input  = g_io_stream_get_input_stream (iostream);
129       tiff_io.output = g_io_stream_get_output_stream (iostream);
130       tiff_io.stream = G_OBJECT (iostream);
131     }
132   else
133     {
134       g_assert_not_reached ();
135     }
136 
137 #if 0
138 #warning FIXME !can_seek code is broken
139   tiff_io.can_seek = g_seekable_can_seek (G_SEEKABLE (tiff_io.stream));
140 #endif
141   tiff_io.can_seek = TRUE;
142 
143   return TIFFClientOpen ("file-tiff", mode,
144                          (thandle_t) &tiff_io,
145                          tiff_io_read,
146                          tiff_io_write,
147                          tiff_io_seek,
148                          tiff_io_close,
149                          tiff_io_get_file_size,
150                          NULL, NULL);
151 }
152 
153 static void
tiff_io_warning(const gchar * module,const gchar * fmt,va_list ap)154 tiff_io_warning (const gchar *module,
155                  const gchar *fmt,
156                  va_list      ap)
157 {
158   gint tag = 0;
159 
160   /* Between libtiff 3.7.0beta2 and 4.0.0alpha. */
161   if (! strcmp (fmt, "%s: unknown field with tag %d (0x%x) encountered") ||
162       /* Before libtiff 3.7.0beta2. */
163       ! strcmp (fmt, "%.1000s: unknown field with tag %d (0x%x) encountered"))
164     {
165       va_list ap_test;
166 
167       G_VA_COPY (ap_test, ap);
168 
169       va_arg (ap_test, const char *); /* ignore first arg */
170 
171       tag = va_arg (ap_test, int);
172 
173       va_end (ap_test);
174     }
175   /* for older versions of libtiff? */
176   else if (! strcmp (fmt, "unknown field with tag %d (0x%x) ignored") ||
177            /* Since libtiff 4.0.0alpha. */
178            ! strcmp (fmt, "Unknown field with tag %d (0x%x) encountered"))
179     {
180       va_list ap_test;
181 
182       G_VA_COPY (ap_test, ap);
183 
184       tag = va_arg (ap_test, int);
185 
186       va_end (ap_test);
187     }
188 
189   /* Workaround for: http://bugzilla.gnome.org/show_bug.cgi?id=131975
190    * Ignore the warnings about unregistered private tags (>= 32768).
191    */
192   if (tag >= 32768)
193     return;
194 
195   /* Other unknown fields are only reported to stderr. */
196   if (tag > 0)
197     {
198       gchar *msg = g_strdup_vprintf (fmt, ap);
199 
200       g_printerr ("%s\n", msg);
201       g_free (msg);
202 
203       return;
204     }
205   else if (! strcmp (module, "TIFFReadDirectory") &&
206            ! strcmp (fmt,
207                      "Sum of Photometric type-related color channels and ExtraSamples doesn't match SamplesPerPixel."
208                      " Defining non-color channels as ExtraSamples."))
209     {
210       /* We will process this issue in our code. Just report to stderr. */
211       g_printerr ("%s: [%s] %s\n", G_STRFUNC, module, fmt);
212 
213       return;
214     }
215   else if (! strcmp (module, "Fax4Decode") ||
216            g_str_has_prefix (module, "Fax3Decode"))
217     {
218       /* Certain corrupt TIFF Fax images can produce a large amount of
219        * warnings which can cause GIMP to run out of GDI resources on
220        * Windows and eventually crash.
221        * The real problem seems to be that the amount of error console
222        * messages does not have a limit.
223        * See e.g. the first page of m1-8110934bb3b18d0e87ccc1ddfc5f0107.tif
224        * from imagetestsuite. LibTiff does not return -1 from
225        * ReadScanline, presumably because for fax images it's not
226        * unreasonable to expect certain lines to fail.
227        * Let's just only report to stderr in this case. */
228       gchar *msg = g_strdup_vprintf (fmt, ap);
229 
230       g_printerr ("LibTiff warning: [%s] %s\n", module, msg);
231       g_free (msg);
232 
233       return;
234     }
235 
236   g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
237 }
238 
239 static void
tiff_io_error(const gchar * module,const gchar * fmt,va_list ap)240 tiff_io_error (const gchar *module,
241                const gchar *fmt,
242                va_list      ap)
243 {
244   /* Workaround for: http://bugzilla.gnome.org/show_bug.cgi?id=132297
245    * Ignore the errors related to random access and JPEG compression
246    */
247   if (! strcmp (fmt, "Compression algorithm does not support random access"))
248     return;
249 
250   g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
251 }
252 
253 static tsize_t
tiff_io_read(thandle_t handle,tdata_t buffer,tsize_t size)254 tiff_io_read (thandle_t handle,
255               tdata_t   buffer,
256               tsize_t   size)
257 {
258   TiffIO *io    = (TiffIO *) handle;
259   GError *error = NULL;
260   gssize  read  = -1;
261 
262   if (io->can_seek)
263     {
264       gsize bytes_read = 0;
265 
266       if (! g_input_stream_read_all (io->input,
267                                      (void *) buffer, (gsize) size,
268                                      &bytes_read,
269                                      NULL, &error))
270         {
271           g_printerr ("%s", error->message);
272           g_clear_error (&error);
273         }
274 
275       read = bytes_read;
276     }
277   else
278     {
279       if (io->position + size > io->used)
280         {
281           gsize missing;
282           gsize bytes_read;
283 
284           missing = io->position + size - io->used;
285 
286           if (io->used + missing > io->allocated)
287             {
288               gchar *new_buffer;
289               gsize  new_size = 1;
290               gsize  needed;
291 
292               needed = io->used + missing - io->allocated;
293               while (new_size < io->allocated + needed)
294                 new_size *= 2;
295 
296               new_buffer = g_try_realloc (io->buffer, new_size);
297               if (! new_buffer)
298                 return -1;
299 
300               io->buffer    = new_buffer;
301               io->allocated = new_size;
302             }
303 
304           if (! g_input_stream_read_all (io->input,
305                                          (void *) (io->buffer + io->used),
306                                          missing,
307                                          &bytes_read, NULL, &error))
308             {
309               g_printerr ("%s", error->message);
310               g_clear_error (&error);
311             }
312 
313           io->used += bytes_read;
314         }
315 
316       g_assert (io->position + size <= io->used);
317 
318       memcpy (buffer, io->buffer + io->position, size);
319       io->position += size;
320 
321       read = size;
322     }
323 
324   return (tsize_t) read;
325 }
326 
327 static tsize_t
tiff_io_write(thandle_t handle,tdata_t buffer,tsize_t size)328 tiff_io_write (thandle_t handle,
329                tdata_t   buffer,
330                tsize_t   size)
331 {
332   TiffIO *io      = (TiffIO *) handle;
333   GError *error   = NULL;
334   gssize  written = -1;
335 
336   if (io->can_seek)
337     {
338       gsize bytes_written = 0;
339 
340       if (! g_output_stream_write_all (io->output,
341                                        (void *) buffer, (gsize) size,
342                                        &bytes_written,
343                                        NULL, &error))
344         {
345           g_printerr ("%s", error->message);
346           g_clear_error (&error);
347         }
348 
349       written = bytes_written;
350     }
351   else
352     {
353       if (io->position + size > io->allocated)
354         {
355           gchar *new_buffer;
356           gsize  new_size;
357 
358           new_size = io->position + size;
359 
360           new_buffer = g_try_realloc (io->buffer, new_size);
361           if (! new_buffer)
362             return -1;
363 
364           io->buffer   = new_buffer;
365           io->allocated = new_size;
366         }
367 
368       g_assert (io->position + size <= io->allocated);
369 
370       memcpy (io->buffer + io->position, buffer, size);
371       io->position += size;
372 
373       io->used = MAX (io->used, io->position);
374 
375       written = size;
376     }
377 
378   return (tsize_t) written;
379 }
380 
381 static GSeekType
lseek_to_seek_type(gint whence)382 lseek_to_seek_type (gint whence)
383 {
384   switch (whence)
385     {
386     default:
387     case SEEK_SET:
388       return G_SEEK_SET;
389 
390     case SEEK_CUR:
391       return G_SEEK_CUR;
392 
393     case SEEK_END:
394       return G_SEEK_END;
395     }
396 }
397 
398 static toff_t
tiff_io_seek(thandle_t handle,toff_t offset,gint whence)399 tiff_io_seek (thandle_t handle,
400               toff_t    offset,
401               gint      whence)
402 {
403   TiffIO   *io       = (TiffIO *) handle;
404   GError   *error    = NULL;
405   gboolean  sought   = FALSE;
406   goffset   position = -1;
407 
408   if (io->can_seek)
409     {
410       sought = g_seekable_seek (G_SEEKABLE (io->stream),
411                                 (goffset) offset, lseek_to_seek_type (whence),
412                                 NULL, &error);
413       if (sought)
414         {
415           position = g_seekable_tell (G_SEEKABLE (io->stream));
416         }
417       else
418         {
419           g_printerr ("%s", error->message);
420           g_clear_error (&error);
421         }
422     }
423   else
424     {
425       switch (whence)
426         {
427         default:
428         case SEEK_SET:
429           if (offset <= io->used)
430             position = io->position = offset;
431           break;
432 
433         case SEEK_CUR:
434           if (io->position + offset <= io->used)
435             position = io->position += offset;
436           break;
437 
438         case G_SEEK_END:
439           if (io->used + offset <= io->used)
440             position = io->position = io->used + offset;
441           break;
442         }
443     }
444 
445   return (toff_t) position;
446 }
447 
448 static gint
tiff_io_close(thandle_t handle)449 tiff_io_close (thandle_t handle)
450 {
451   TiffIO   *io     = (TiffIO *) handle;
452   GError   *error  = NULL;
453   gboolean  closed = FALSE;
454 
455   if (io->input && ! io->output)
456     {
457       closed = g_input_stream_close (io->input, NULL, &error);
458     }
459   else
460     {
461       if (! io->can_seek && io->buffer && io->allocated)
462         {
463           if (! g_output_stream_write_all (io->output,
464                                            (void *) io->buffer,
465                                            io->allocated,
466                                            NULL, NULL, &error))
467             {
468               g_printerr ("%s", error->message);
469               g_clear_error (&error);
470             }
471         }
472 
473       if (io->input)
474         {
475           closed = g_io_stream_close (G_IO_STREAM (io->stream), NULL, &error);
476         }
477       else
478         {
479           closed = g_output_stream_close (io->output, NULL, &error);
480         }
481     }
482 
483   if (! closed)
484     {
485       g_printerr ("%s", error->message);
486       g_clear_error (&error);
487     }
488 
489   g_object_unref (io->stream);
490   io->stream = NULL;
491   io->input  = NULL;
492   io->output = NULL;
493 
494   g_free (io->buffer);
495   io->buffer = NULL;
496 
497   io->allocated = 0;
498   io->used      = 0;
499   io->position  = 0;
500 
501   return closed ? 0 : -1;
502 }
503 
504 static toff_t
tiff_io_get_file_size(thandle_t handle)505 tiff_io_get_file_size (thandle_t handle)
506 {
507   TiffIO    *io    = (TiffIO *) handle;
508   GError    *error = NULL;
509   GFileInfo *info;
510   goffset    size = 0;
511 
512   info = g_file_query_info (io->file,
513                             G_FILE_ATTRIBUTE_STANDARD_SIZE,
514                             G_FILE_QUERY_INFO_NONE,
515                             NULL, &error);
516   if (! info)
517     {
518       g_printerr ("%s", error->message);
519       g_clear_error (&error);
520     }
521   else
522     {
523       size = g_file_info_get_size (info);
524       g_object_unref (info);
525     }
526 
527   return (toff_t) size;
528 }
529