1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 /* GdkPixbuf library - TIFF image loader
3  *
4  * Copyright (C) 1999 Mark Crichton
5  * Copyright (C) 1999 The Free Software Foundation
6  *
7  * Authors: Mark Crichton <crichton@gimp.org>
8  *          Federico Mena-Quintero <federico@gimp.org>
9  *          Jonathan Blandford <jrb@redhat.com>
10  *          S�ren Sandmann <sandmann@daimi.au.dk>
11  *          Christian Dywan <christian@lanedo.com>
12  *          Mukund Sivaraman <muks@banu.com>
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 /* Following code (almost) blatantly ripped from Imlib */
29 
30 #include "config.h"
31 #include <stdlib.h>
32 #include <string.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <tiffio.h>
37 #include <errno.h>
38 #include <glib-object.h>
39 #include <glib/gi18n-lib.h>
40 
41 #include "gdk-pixbuf-core.h"
42 #include "gdk-pixbuf-io.h"
43 #include "fallback-c89.c"
44 
45 #ifdef G_OS_WIN32
46 #include <fcntl.h>
47 #include <io.h>
48 #include <windows.h>
49 #define lseek(a,b,c) _lseek(a,b,c)
50 #define O_RDWR _O_RDWR
51 #endif
52 
53 
54 /* Helper macros to convert between density units */
55 #define DPCM_TO_DPI(value) ((int) round ((value) * 2.54))
56 
57 typedef struct _TiffContext TiffContext;
58 struct _TiffContext
59 {
60 	GdkPixbufModuleSizeFunc size_func;
61 	GdkPixbufModulePreparedFunc prepare_func;
62 	GdkPixbufModuleUpdatedFunc update_func;
63 	gpointer user_data;
64 
65         guchar *buffer;
66         guint allocated;
67         guint used;
68         guint pos;
69 };
70 
71 static void
tiff_warning_handler(const char * mod,const char * fmt,va_list ap)72 tiff_warning_handler (const char *mod, const char *fmt, va_list ap)
73 {
74         /* Don't print anything; we should not be dumping junk to
75          * stderr, since that may be bad for some apps.
76          */
77 }
78 
79 static void
tiff_set_handlers(void)80 tiff_set_handlers (void)
81 {
82         TIFFSetErrorHandler (tiff_warning_handler);
83         TIFFSetWarningHandler (tiff_warning_handler);
84 }
85 
86 
87 
free_buffer(guchar * pixels,gpointer data)88 static void free_buffer (guchar *pixels, gpointer data)
89 {
90 	g_free (pixels);
91 }
92 
93 static GdkPixbuf *
tiff_image_parse(TIFF * tiff,TiffContext * context,GError ** error)94 tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
95 {
96 	guchar *pixels = NULL;
97 	gint width, height, rowstride, bytes;
98 	GdkPixbuf *pixbuf;
99 	guint16 bits_per_sample = 0;
100 	uint16 orientation = 0;
101 	uint16 transform = 0;
102         uint16 codec;
103         gchar *icc_profile_base64;
104         const gchar *icc_profile;
105         guint icc_profile_size;
106         uint16 resolution_unit;
107         gchar *density_str;
108         gint retval;
109 
110         /* We're called with the lock held. */
111 
112 	if (!TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width)) {
113                 g_set_error_literal (error,
114                                      GDK_PIXBUF_ERROR,
115                                      GDK_PIXBUF_ERROR_FAILED,
116                                      _("Could not get image width (bad TIFF file)"));
117                 return NULL;
118         }
119 
120         if (!TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height)) {
121                 g_set_error_literal (error,
122                                      GDK_PIXBUF_ERROR,
123                                      GDK_PIXBUF_ERROR_FAILED,
124                                      _("Could not get image height (bad TIFF file)"));
125                 return NULL;
126         }
127 
128         if (width <= 0 || height <= 0) {
129                 g_set_error_literal (error,
130                                      GDK_PIXBUF_ERROR,
131                                      GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
132                                      _("Width or height of TIFF image is zero"));
133                 return NULL;
134         }
135 
136         if (width > G_MAXINT / 4) { /* overflow */
137                 g_set_error_literal (error,
138                                      GDK_PIXBUF_ERROR,
139                                      GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
140                                      _("Dimensions of TIFF image too large"));
141                 return NULL;
142         }
143 
144         rowstride = width * 4;
145 
146         if (height > G_MAXINT / rowstride) { /* overflow */
147                 g_set_error_literal (error,
148                                      GDK_PIXBUF_ERROR,
149                                      GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
150                                      _("Dimensions of TIFF image too large"));
151                 return NULL;
152         }
153 
154         bytes = height * rowstride;
155 
156 	if (context && context->size_func) {
157                 gint w = width;
158                 gint h = height;
159 		(* context->size_func) (&w, &h, context->user_data);
160 
161 		/* This is a signal that this function is being called
162 		   to support gdk_pixbuf_get_file_info, so we can stop
163 		   parsing the tiff file at this point. It is not an
164 		   error condition. */
165 
166                 if (w == 0 || h == 0)
167                     return NULL;
168         }
169 
170         pixels = g_try_malloc (bytes);
171 
172         if (!pixels) {
173                 g_set_error_literal (error,
174                                      GDK_PIXBUF_ERROR,
175                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
176                                      _("Insufficient memory to open TIFF file"));
177                 return NULL;
178         }
179 
180 	pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8,
181                                            width, height, rowstride,
182                                            free_buffer, NULL);
183         if (!pixbuf) {
184                 g_free (pixels);
185                 g_set_error_literal (error,
186                                      GDK_PIXBUF_ERROR,
187                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
188                                      _("Insufficient memory to open TIFF file"));
189                 return NULL;
190         }
191 
192         /* Save the bits per sample as an option since pixbufs are
193            expected to be always 8 bits per sample. */
194         TIFFGetField (tiff, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
195         if (bits_per_sample > 0) {
196                 gchar str[5];
197                 g_snprintf (str, sizeof (str), "%d", bits_per_sample);
198                 gdk_pixbuf_set_option (pixbuf, "bits-per-sample", str);
199         }
200 
201 	/* Set the "orientation" key associated with this image. libtiff
202 	   orientation handling is odd, so further processing is required
203 	   by higher-level functions based on this tag. If the embedded
204 	   orientation tag is 1-4, libtiff flips/mirrors the image as
205 	   required, and no client processing is required - so we report
206 	   no orientation. Orientations 5-8 require rotations which would
207 	   swap the width and height of the image. libtiff does not do this.
208 	   Instead it interprets orientations 5-8 the same as 1-4.
209 	   See http://bugzilla.remotesensing.org/show_bug.cgi?id=1548.
210 	   To correct for this, the client must apply the transform normally
211 	   used for orientation 5 to both orientations 5 and 7, and apply
212 	   the transform normally used for orientation 7 for both
213 	   orientations 6 and 8. Then everythings works out OK! */
214 
215 	TIFFGetField (tiff, TIFFTAG_ORIENTATION, &orientation);
216 
217 	switch (orientation) {
218 		case 5:
219 		case 7:
220 			transform = 5;
221 			break;
222 		case 6:
223 		case 8:
224 			transform = 7;
225 			break;
226 		default:
227 			transform = 0;
228 			break;
229 	}
230 
231 	if (transform > 0 ) {
232 		gchar str[5];
233 		g_snprintf (str, sizeof (str), "%d", transform);
234 		gdk_pixbuf_set_option (pixbuf, "orientation", str);
235 	}
236 
237         TIFFGetField (tiff, TIFFTAG_COMPRESSION, &codec);
238         if (codec > 0) {
239           gchar str[5];
240           g_snprintf (str, sizeof (str), "%d", codec);
241           gdk_pixbuf_set_option (pixbuf, "compression", str);
242         }
243 
244         /* Extract embedded ICC profile */
245         retval = TIFFGetField (tiff, TIFFTAG_ICCPROFILE, &icc_profile_size, &icc_profile);
246         if (retval == 1) {
247                 icc_profile_base64 = g_base64_encode ((const guchar *) icc_profile, icc_profile_size);
248                 gdk_pixbuf_set_option (pixbuf, "icc-profile", icc_profile_base64);
249                 g_free (icc_profile_base64);
250         }
251 
252         retval = TIFFGetField (tiff, TIFFTAG_RESOLUTIONUNIT, &resolution_unit);
253         if (retval == 1) {
254                 float x_resolution = 0, y_resolution = 0;
255 
256                 TIFFGetField (tiff, TIFFTAG_XRESOLUTION, &x_resolution);
257                 TIFFGetField (tiff, TIFFTAG_YRESOLUTION, &y_resolution);
258 
259                 switch (resolution_unit) {
260                 case RESUNIT_INCH:
261                         density_str = g_strdup_printf ("%d", (int) round (x_resolution));
262                         gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
263                         g_free (density_str);
264                         density_str = g_strdup_printf ("%d", (int) round (y_resolution));
265                         gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
266                         g_free (density_str);
267                         break;
268                 case RESUNIT_CENTIMETER:
269                         density_str = g_strdup_printf ("%d", DPCM_TO_DPI (x_resolution));
270                         gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
271                         g_free (density_str);
272                         density_str = g_strdup_printf ("%d", DPCM_TO_DPI (y_resolution));
273                         gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
274                         g_free (density_str);
275                         break;
276                 }
277         }
278 
279 	if (context && context->prepare_func)
280 		(* context->prepare_func) (pixbuf, NULL, context->user_data);
281 
282 	if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32 *)pixels, ORIENTATION_TOPLEFT, 1)) {
283 		g_set_error_literal (error,
284                                      GDK_PIXBUF_ERROR,
285                                      GDK_PIXBUF_ERROR_FAILED,
286                                      _("Failed to load RGB data from TIFF file"));
287 		g_object_unref (pixbuf);
288 		return NULL;
289 	}
290 
291 	/* Flag multi-page documents, because this loader only handles the
292 	   first page. The client app may wish to warn the user. */
293         if (TIFFReadDirectory (tiff))
294                 gdk_pixbuf_set_option (pixbuf, "multipage", "yes");
295 
296 #if G_BYTE_ORDER == G_BIG_ENDIAN
297         {
298                 guchar *pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf);
299 
300                 pixels = pixbuf_pixels;
301 
302                 /* Turns out that the packing used by TIFFRGBAImage depends on
303                  * the host byte order...
304                  */
305                 while (pixels < pixbuf_pixels + bytes) {
306                         uint32 pixel = *(uint32 *)pixels;
307                         int r = TIFFGetR(pixel);
308                         int g = TIFFGetG(pixel);
309                         int b = TIFFGetB(pixel);
310                         int a = TIFFGetA(pixel);
311                         *pixels++ = r;
312                         *pixels++ = g;
313                         *pixels++ = b;
314                         *pixels++ = a;
315                 }
316         }
317 #endif
318 
319 	if (context && context->update_func)
320 		(* context->update_func) (pixbuf, 0, 0, width, height, context->user_data);
321 
322         return pixbuf;
323 }
324 
325 
326 
327 /* Static loader */
328 
329 static GdkPixbuf *
gdk_pixbuf__tiff_image_load(FILE * f,GError ** error)330 gdk_pixbuf__tiff_image_load (FILE *f, GError **error)
331 {
332         TIFF *tiff = NULL;
333         int fd;
334         GdkPixbuf *pixbuf;
335 
336         g_return_val_if_fail (f != NULL, NULL);
337 
338         tiff_set_handlers ();
339 
340         fd = fileno (f);
341 
342         /* On OSF, apparently fseek() works in some on-demand way, so
343          * the fseek gdk_pixbuf_new_from_file() doesn't work here
344          * since we are using the raw file descriptor. So, we call lseek() on the fd
345          * before using it. (#60840)
346          */
347         lseek (fd, 0, SEEK_SET);
348 #ifndef G_OS_WIN32
349         tiff = TIFFFdOpen (fd, "libpixbuf-tiff", "r");
350 #else
351         /* W32 version of this function takes HANDLE.
352          * What's worse, the caller will close the file,
353          * but TIFFClose() will *also* close it, so we
354          * need to make a duplicate.
355          */
356         {
357                 HANDLE h;
358 
359                 if (DuplicateHandle (GetCurrentProcess (),
360                                      (HANDLE) _get_osfhandle (fd),
361                                      GetCurrentProcess (),
362                                      &h,
363                                      0,
364                                      FALSE,
365                                      DUPLICATE_SAME_ACCESS)) {
366                         tiff = TIFFFdOpen ((intptr_t) h, "libpixbuf-tiff", "r");
367                         if (tiff == NULL)
368                                 CloseHandle (h);
369                 }
370         }
371 #endif
372 
373         if (!tiff) {
374                 g_set_error_literal (error,
375                                      GDK_PIXBUF_ERROR,
376                                      GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
377                                      _("Failed to open TIFF image"));
378                 return NULL;
379         }
380 
381         pixbuf = tiff_image_parse (tiff, NULL, error);
382 
383         TIFFClose (tiff);
384 
385         return pixbuf;
386 }
387 
388 
389 
390 /* Progressive loader */
391 
392 static gpointer
gdk_pixbuf__tiff_image_begin_load(GdkPixbufModuleSizeFunc size_func,GdkPixbufModulePreparedFunc prepare_func,GdkPixbufModuleUpdatedFunc update_func,gpointer user_data,GError ** error)393 gdk_pixbuf__tiff_image_begin_load (GdkPixbufModuleSizeFunc size_func,
394                                    GdkPixbufModulePreparedFunc prepare_func,
395 				   GdkPixbufModuleUpdatedFunc update_func,
396 				   gpointer user_data,
397                                    GError **error)
398 {
399 	TiffContext *context;
400 
401 	context = g_new0 (TiffContext, 1);
402 	context->size_func = size_func;
403 	context->prepare_func = prepare_func;
404 	context->update_func = update_func;
405 	context->user_data = user_data;
406         context->buffer = NULL;
407         context->allocated = 0;
408         context->used = 0;
409         context->pos = 0;
410 
411 	return context;
412 }
413 
414 static tsize_t
tiff_load_read(thandle_t handle,tdata_t buf,tsize_t size)415 tiff_load_read (thandle_t handle, tdata_t buf, tsize_t size)
416 {
417         TiffContext *context = (TiffContext *)handle;
418 
419         if (context->pos + size > context->used)
420                 return 0;
421 
422         memcpy (buf, context->buffer + context->pos, size);
423         context->pos += size;
424         return size;
425 }
426 
427 static tsize_t
tiff_load_write(thandle_t handle,tdata_t buf,tsize_t size)428 tiff_load_write (thandle_t handle, tdata_t buf, tsize_t size)
429 {
430         return -1;
431 }
432 
433 static toff_t
tiff_load_seek(thandle_t handle,toff_t offset,int whence)434 tiff_load_seek (thandle_t handle, toff_t offset, int whence)
435 {
436         TiffContext *context = (TiffContext *)handle;
437 
438         switch (whence) {
439         case SEEK_SET:
440                 if (offset > context->used)
441                         return -1;
442                 context->pos = offset;
443                 break;
444         case SEEK_CUR:
445                 if (offset + context->pos >= context->used)
446                         return -1;
447                 context->pos += offset;
448                 break;
449         case SEEK_END:
450                 if (offset + context->used > context->used)
451                         return -1;
452                 context->pos = context->used + offset;
453                 break;
454         default:
455                 return -1;
456         }
457         return context->pos;
458 }
459 
460 static int
tiff_load_close(thandle_t context)461 tiff_load_close (thandle_t context)
462 {
463         return 0;
464 }
465 
466 static toff_t
tiff_load_size(thandle_t handle)467 tiff_load_size (thandle_t handle)
468 {
469         TiffContext *context = (TiffContext *)handle;
470 
471         return context->used;
472 }
473 
474 static int
tiff_load_map_file(thandle_t handle,tdata_t * buf,toff_t * size)475 tiff_load_map_file (thandle_t handle, tdata_t *buf, toff_t *size)
476 {
477         TiffContext *context = (TiffContext *)handle;
478 
479         *buf = context->buffer;
480         *size = context->used;
481 
482         return 0;
483 }
484 
485 static void
tiff_load_unmap_file(thandle_t handle,tdata_t data,toff_t offset)486 tiff_load_unmap_file (thandle_t handle, tdata_t data, toff_t offset)
487 {
488 }
489 
490 static gboolean
gdk_pixbuf__tiff_image_stop_load(gpointer data,GError ** error)491 gdk_pixbuf__tiff_image_stop_load (gpointer data,
492                                   GError **error)
493 {
494         TiffContext *context = data;
495         TIFF *tiff;
496         gboolean retval = FALSE;
497 
498         g_return_val_if_fail (data != NULL, FALSE);
499 
500         tiff_set_handlers ();
501 
502         tiff = TIFFClientOpen ("libtiff-pixbuf", "r", data,
503                                tiff_load_read, tiff_load_write,
504                                tiff_load_seek, tiff_load_close,
505                                tiff_load_size,
506                                tiff_load_map_file, tiff_load_unmap_file);
507         if (!tiff) {
508                 g_set_error_literal (error,
509                                      GDK_PIXBUF_ERROR,
510                                      GDK_PIXBUF_ERROR_FAILED,
511                                      _("Failed to load TIFF image"));
512         } else {
513                 GdkPixbuf *pixbuf;
514 
515                 pixbuf = tiff_image_parse (tiff, context, error);
516                 retval = (pixbuf != NULL);
517                 g_clear_object (&pixbuf);
518                 /* tiff_image_parse() can return NULL on success in a particular case */
519                 if (!retval && error && !*error) {
520                         g_set_error_literal (error,
521                                              GDK_PIXBUF_ERROR,
522                                              GDK_PIXBUF_ERROR_FAILED,
523                                              _("Failed to load TIFF image"));
524                 }
525         }
526 
527         if (tiff)
528                 TIFFClose (tiff);
529 
530         g_free (context->buffer);
531         g_free (context);
532 
533         return retval;
534 }
535 
536 static gboolean
make_available_at_least(TiffContext * context,guint needed)537 make_available_at_least (TiffContext *context, guint needed)
538 {
539         guchar *new_buffer = NULL;
540         guint need_alloc;
541 
542         need_alloc = context->used + needed;
543         if (need_alloc > context->allocated) {
544                 guint new_size = 1;
545                 while (new_size < need_alloc) {
546                         if (!g_uint_checked_mul (&new_size, new_size, 2)) {
547                                 new_size = 0;
548                                 break;
549                         }
550                 }
551 
552                 if (new_size == 0)
553                         return FALSE;
554 
555                 new_buffer = g_try_realloc (context->buffer, new_size);
556                 if (new_buffer) {
557                         context->buffer = new_buffer;
558                         context->allocated = new_size;
559                         return TRUE;
560                 }
561                 return FALSE;
562         }
563         return TRUE;
564 }
565 
566 static gboolean
gdk_pixbuf__tiff_image_load_increment(gpointer data,const guchar * buf,guint size,GError ** error)567 gdk_pixbuf__tiff_image_load_increment (gpointer data, const guchar *buf,
568                                        guint size, GError **error)
569 {
570 	TiffContext *context = (TiffContext *) data;
571 
572 	g_return_val_if_fail (data != NULL, FALSE);
573 
574         tiff_set_handlers ();
575 
576         if (!make_available_at_least (context, size)) {
577                 g_set_error_literal (error,
578                                      GDK_PIXBUF_ERROR,
579                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
580                                      _("Insufficient memory to open TIFF file"));
581                 return FALSE;
582         }
583 
584         memcpy (context->buffer + context->used, buf, size);
585         context->used += size;
586 	return TRUE;
587 }
588 
589 typedef struct {
590         gchar *buffer;
591         guint allocated;
592         guint used;
593         guint pos;
594 } TiffSaveContext;
595 
596 static tsize_t
tiff_save_read(thandle_t handle,tdata_t buf,tsize_t size)597 tiff_save_read (thandle_t handle, tdata_t buf, tsize_t size)
598 {
599         return -1;
600 }
601 
602 static tsize_t
tiff_save_write(thandle_t handle,tdata_t buf,tsize_t size)603 tiff_save_write (thandle_t handle, tdata_t buf, tsize_t size)
604 {
605         TiffSaveContext *context = (TiffSaveContext *)handle;
606 
607         /* Modify buffer length */
608         if (context->pos + size > context->used)
609                 context->used = context->pos + size;
610 
611         /* Realloc */
612         if (context->used > context->allocated) {
613                 context->buffer = g_realloc (context->buffer, context->pos + size);
614                 context->allocated = context->used;
615         }
616 
617         /* Now copy the data */
618         memcpy (context->buffer + context->pos, buf, size);
619 
620         /* Update pos */
621         context->pos += size;
622 
623         return size;
624 }
625 
626 static toff_t
tiff_save_seek(thandle_t handle,toff_t offset,int whence)627 tiff_save_seek (thandle_t handle, toff_t offset, int whence)
628 {
629         TiffSaveContext *context = (TiffSaveContext *)handle;
630 
631         switch (whence) {
632         case SEEK_SET:
633                 context->pos = offset;
634                 break;
635         case SEEK_CUR:
636                 context->pos += offset;
637                 break;
638         case SEEK_END:
639                 context->pos = context->used + offset;
640                 break;
641         default:
642                 return -1;
643         }
644         return context->pos;
645 }
646 
647 static int
tiff_save_close(thandle_t context)648 tiff_save_close (thandle_t context)
649 {
650         return 0;
651 }
652 
653 static toff_t
tiff_save_size(thandle_t handle)654 tiff_save_size (thandle_t handle)
655 {
656         return -1;
657 }
658 
659 static TiffSaveContext *
create_save_context(void)660 create_save_context (void)
661 {
662         TiffSaveContext *context;
663 
664         context = g_new (TiffSaveContext, 1);
665         context->buffer = NULL;
666         context->allocated = 0;
667         context->used = 0;
668         context->pos = 0;
669 
670         return context;
671 }
672 
673 static void
free_save_context(TiffSaveContext * context)674 free_save_context (TiffSaveContext *context)
675 {
676         g_free (context->buffer);
677         g_free (context);
678 }
679 
680 static void
copy_gray_row(gint * dest,guchar * src,gint width,gboolean has_alpha)681 copy_gray_row (gint     *dest,
682                guchar   *src,
683                gint      width,
684                gboolean  has_alpha)
685 {
686         gint i;
687         guchar *p;
688 
689         p = src;
690         for (i = 0; i < width; i++) {
691                 int pr, pg, pb, pv;
692 
693                 pr = *p++;
694                 pg = *p++;
695                 pb = *p++;
696 
697                 if (has_alpha) {
698                         int pa = *p++;
699 
700                         /* Premul alpha to simulate it */
701                         if (pa > 0) {
702                                 pr = pr * pa / 255;
703                                 pg = pg * pa / 255;
704                                 pb = pb * pa / 255;
705                         } else {
706                                 pr = pg = pb = 0;
707                         }
708                 }
709 
710                 /* Calculate value MAX(MAX(r,g),b) */
711                 pv = pr > pg ? pr : pg;
712                 pv = pv > pb ? pv : pb;
713 
714                 *dest++ = pv;
715         }
716 }
717 
718 static gboolean
gdk_pixbuf__tiff_image_save_to_callback(GdkPixbufSaveFunc save_func,gpointer user_data,GdkPixbuf * pixbuf,gchar ** keys,gchar ** values,GError ** error)719 gdk_pixbuf__tiff_image_save_to_callback (GdkPixbufSaveFunc   save_func,
720                                          gpointer            user_data,
721                                          GdkPixbuf          *pixbuf,
722                                          gchar             **keys,
723                                          gchar             **values,
724                                          GError            **error)
725 {
726         TIFF *tiff;
727         gint width, height, rowstride;
728         const gchar *bits_per_sample = NULL;
729         long bps;
730         const gchar *compression = NULL;
731         guchar *pixels;
732         gboolean has_alpha;
733         gushort alpha_samples[1] = { EXTRASAMPLE_UNASSALPHA };
734         int y;
735         TiffSaveContext *context;
736         gboolean retval;
737         const gchar *icc_profile = NULL;
738         const gchar *x_dpi = NULL;
739         const gchar *y_dpi = NULL;
740         guint16 codec;
741 
742         tiff_set_handlers ();
743 
744         context = create_save_context ();
745         tiff = TIFFClientOpen ("libtiff-pixbuf", "w", context,
746                                tiff_save_read, tiff_save_write,
747                                tiff_save_seek, tiff_save_close,
748                                tiff_save_size,
749                                NULL, NULL);
750 
751         if (!tiff) {
752                 g_set_error_literal (error,
753                                      GDK_PIXBUF_ERROR,
754                                      GDK_PIXBUF_ERROR_FAILED,
755                                      _("Failed to save TIFF image"));
756                 free_save_context (context);
757                 return FALSE;
758         }
759 
760         rowstride = gdk_pixbuf_get_rowstride (pixbuf);
761         pixels = gdk_pixbuf_get_pixels (pixbuf);
762 
763         has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
764 
765         height = gdk_pixbuf_get_height (pixbuf);
766         width = gdk_pixbuf_get_width (pixbuf);
767 
768         /* Guaranteed by the caller. */
769         g_assert (width >= 0);
770         g_assert (height >= 0);
771         g_assert (rowstride >= 0);
772 
773         TIFFSetField (tiff, TIFFTAG_IMAGEWIDTH, width);
774         TIFFSetField (tiff, TIFFTAG_IMAGELENGTH, height);
775 
776         /* libtiff supports a number of 'codecs' such as:
777            1 None, 2 Huffman, 5 LZW, 7 JPEG, 8 Deflate, see tiff.h */
778         if (keys && *keys && values && *values) {
779             guint i = 0;
780 
781             while (keys[i]) {
782                     if (g_str_equal (keys[i], "bits-per-sample"))
783                             bits_per_sample = values[i];
784                     else if (g_str_equal (keys[i], "compression"))
785                             compression = values[i];
786                     else if (g_str_equal (keys[i], "icc-profile"))
787                             icc_profile = values[i];
788                     else if (g_str_equal (keys[i], "x-dpi"))
789                             x_dpi = values[i];
790                     else if (g_str_equal (keys[i], "y-dpi"))
791                             y_dpi = values[i];
792                    i++;
793             }
794         }
795 
796         /* Use 8 bits per sample by default, if none was recorded or
797            specified. */
798         if (!bits_per_sample)
799                 bits_per_sample = "8";
800 
801         /* Use DEFLATE compression (8) by default, if none was recorded
802            or specified. */
803         if (!compression)
804                 compression = "8";
805 
806         /* libtiff supports a number of 'codecs' such as:
807            1 None, 2 Huffman, 5 LZW, 7 JPEG, 8 Deflate, see tiff.h */
808         codec = strtol (compression, NULL, 0);
809 
810         if (TIFFIsCODECConfigured (codec))
811                 TIFFSetField (tiff, TIFFTAG_COMPRESSION, codec);
812         else {
813                 g_set_error_literal (error,
814                                      GDK_PIXBUF_ERROR,
815                                      GDK_PIXBUF_ERROR_FAILED,
816                                      _("TIFF compression doesn’t refer to a valid codec."));
817                 retval = FALSE;
818                 goto cleanup;
819         }
820 
821         /* We support 1-bit or 8-bit saving */
822         bps = atol (bits_per_sample);
823         if (bps == 1) {
824                 TIFFSetField (tiff, TIFFTAG_BITSPERSAMPLE, 1);
825                 TIFFSetField (tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
826                 TIFFSetField (tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
827                 TIFFSetField (tiff, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
828         } else if (bps == 8) {
829                 TIFFSetField (tiff, TIFFTAG_BITSPERSAMPLE, 8);
830                 TIFFSetField (tiff, TIFFTAG_SAMPLESPERPIXEL, has_alpha ? 4 : 3);
831                 TIFFSetField (tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
832 
833                 if (has_alpha)
834                         TIFFSetField (tiff, TIFFTAG_EXTRASAMPLES, 1, alpha_samples);
835 
836                 if (icc_profile != NULL) {
837                         guchar *icc_profile_buf;
838                         gsize icc_profile_size;
839 
840                         /* decode from base64 */
841                         icc_profile_buf = g_base64_decode (icc_profile, &icc_profile_size);
842                         if (icc_profile_size < 127) {
843                                 g_set_error (error,
844                                              GDK_PIXBUF_ERROR,
845                                              GDK_PIXBUF_ERROR_BAD_OPTION,
846                                              _("Color profile has invalid length %d."),
847                                              (gint) icc_profile_size);
848                                 retval = FALSE;
849                                 g_free (icc_profile_buf);
850                                 goto cleanup;
851                         }
852 
853                         TIFFSetField (tiff, TIFFTAG_ICCPROFILE, icc_profile_size, icc_profile_buf);
854                         g_free (icc_profile_buf);
855                 }
856         } else {
857                 /* The passed bits-per-sample is not supported. */
858                 g_set_error_literal (error,
859                                      GDK_PIXBUF_ERROR,
860                                      GDK_PIXBUF_ERROR_FAILED,
861                                      _("TIFF bits-per-sample doesn’t contain a supported value."));
862                 retval = FALSE;
863                 goto cleanup;
864          }
865 
866         TIFFSetField (tiff, TIFFTAG_ROWSPERSTRIP, height);
867         TIFFSetField (tiff, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
868         TIFFSetField (tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
869 
870         if (bps == 1) {
871                 guchar *mono_row;
872                 gint *dith_row_1, *dith_row_2, *dith_row_tmp;
873 
874                 dith_row_1 = g_new (gint, width);
875                 dith_row_2 = g_new (gint, width);
876                 mono_row = g_malloc ((width + 7) / 8);
877 
878                 copy_gray_row (dith_row_1, pixels, width, has_alpha);
879 
880                 for (y = 0; y < height; y++) {
881                         guint x;
882                         gint *p;
883 
884                         memset (mono_row, 0, (width + 7) / 8);
885 
886                         if (y > 0) {
887                                 dith_row_tmp = dith_row_1;
888                                 dith_row_1 = dith_row_2;
889                                 dith_row_2 = dith_row_tmp;
890                         }
891 
892                         if (y < (height - 1))
893                                 copy_gray_row (dith_row_2, pixels + ((y + 1) * rowstride), width, has_alpha);
894 
895                         p = dith_row_1;
896                         for (x = 0; x < width; x++) {
897                                 gint p_old, p_new, quant_error;
898 
899                                 /* Apply Floyd-Steinberg dithering */
900 
901                                 p_old = *p++;
902 
903                                 if (p_old > 127)
904                                         p_new = 255;
905                                 else
906                                         p_new = 0;
907 
908                                 quant_error = p_old - p_new;
909                                 if (x < (width - 1))
910                                         dith_row_1[x + 1] += 7 * quant_error / 16;
911                                 if (y < (height - 1)) {
912                                         if (x > 0)
913                                                 dith_row_2[x - 1] += 3 * quant_error / 16;
914 
915                                         dith_row_2[x] += 5 * quant_error / 16;
916 
917                                         if (x < (width - 1))
918                                                 dith_row_2[x + 1] += quant_error / 16;
919                                 }
920 
921                                 if (p_new > 127)
922                                         mono_row[x / 8] |= (0x1 << (7 - (x % 8)));
923                         }
924 
925                         if (TIFFWriteScanline (tiff, mono_row, y, 0) == -1)
926                                 break;
927                 }
928                 g_free (mono_row);
929                 g_free (dith_row_1);
930                 g_free (dith_row_2);
931         } else {
932                 for (y = 0; y < height; y++) {
933                         if (TIFFWriteScanline (tiff, pixels + y * rowstride, y, 0) == -1)
934                                 break;
935                 }
936         }
937 
938         if (y < height) {
939                 g_set_error_literal (error,
940                                      GDK_PIXBUF_ERROR,
941                                      GDK_PIXBUF_ERROR_FAILED,
942                                      _("Failed to write TIFF data"));
943                 TIFFClose (tiff);
944                 retval = FALSE;
945                 goto cleanup;
946         }
947 
948         if (x_dpi != NULL && y_dpi != NULL) {
949                 char *endptr = NULL;
950                 uint16 resolution_unit = RESUNIT_INCH;
951                 float x_dpi_value, y_dpi_value;
952 
953                 x_dpi_value = strtol (x_dpi, &endptr, 10);
954                 if (x_dpi[0] != '\0' && *endptr != '\0')
955                         x_dpi_value = -1;
956                 if (x_dpi_value <= 0) {
957                     g_set_error (error,
958                                  GDK_PIXBUF_ERROR,
959                                  GDK_PIXBUF_ERROR_BAD_OPTION,
960                                  _("TIFF x-dpi must be greater than zero; value “%s” is not allowed."),
961                                  x_dpi);
962                     retval = FALSE;
963                     goto cleanup;
964                 }
965                 y_dpi_value = strtol (y_dpi, &endptr, 10);
966                 if (y_dpi[0] != '\0' && *endptr != '\0')
967                         y_dpi_value = -1;
968                 if (y_dpi_value <= 0) {
969                     g_set_error (error,
970                                  GDK_PIXBUF_ERROR,
971                                  GDK_PIXBUF_ERROR_BAD_OPTION,
972                                  _("TIFF y-dpi must be greater than zero; value “%s” is not allowed."),
973                                  y_dpi);
974                     retval = FALSE;
975                     goto cleanup;
976                 }
977 
978                 TIFFSetField (tiff, TIFFTAG_RESOLUTIONUNIT, resolution_unit);
979                 TIFFSetField (tiff, TIFFTAG_XRESOLUTION, x_dpi_value);
980                 TIFFSetField (tiff, TIFFTAG_YRESOLUTION, y_dpi_value);
981         }
982 
983         TIFFClose (tiff);
984 
985         /* Now call the callback */
986         retval = save_func (context->buffer, context->used, error, user_data);
987 
988 cleanup:
989         free_save_context (context);
990         return retval;
991 }
992 
993 static gboolean
save_to_file_cb(const gchar * buf,gsize count,GError ** error,gpointer data)994 save_to_file_cb (const gchar *buf,
995 		 gsize count,
996 		 GError **error,
997 		 gpointer data)
998 {
999 	gint bytes;
1000 
1001 	while (count > 0) {
1002 		bytes = fwrite (buf, sizeof (gchar), count, (FILE *) data);
1003 		if (bytes <= 0)
1004 			break;
1005 		count -= bytes;
1006 		buf += bytes;
1007 	}
1008 
1009 	if (count) {
1010 		g_set_error_literal (error,
1011                                      GDK_PIXBUF_ERROR,
1012                                      GDK_PIXBUF_ERROR_FAILED,
1013                                      _("Couldn’t write to TIFF file"));
1014 		return FALSE;
1015 	}
1016 
1017 	return TRUE;
1018 }
1019 
1020 static gboolean
gdk_pixbuf__tiff_image_save(FILE * f,GdkPixbuf * pixbuf,gchar ** keys,gchar ** values,GError ** error)1021 gdk_pixbuf__tiff_image_save (FILE          *f,
1022                              GdkPixbuf     *pixbuf,
1023                              gchar        **keys,
1024                              gchar        **values,
1025                              GError       **error)
1026 {
1027 	return gdk_pixbuf__tiff_image_save_to_callback (save_to_file_cb,
1028                                                         f, pixbuf, keys,
1029                                                         values, error);
1030 }
1031 
1032 static gboolean
gdk_pixbuf__tiff_is_save_option_supported(const gchar * option_key)1033 gdk_pixbuf__tiff_is_save_option_supported (const gchar *option_key)
1034 {
1035         if (g_strcmp0 (option_key, "bits-per-sample") == 0 ||
1036             g_strcmp0 (option_key, "compression") == 0 ||
1037             g_strcmp0 (option_key, "icc-profile") == 0 ||
1038             g_strcmp0 (option_key, "x-dpi") == 0 ||
1039             g_strcmp0 (option_key, "y-dpi") == 0)
1040                 return TRUE;
1041 
1042         return FALSE;
1043 }
1044 
1045 #ifndef INCLUDE_tiff
1046 #define MODULE_ENTRY(function) G_MODULE_EXPORT void function
1047 #else
1048 #define MODULE_ENTRY(function) void _gdk_pixbuf__tiff_ ## function
1049 #endif
1050 
MODULE_ENTRY(fill_vtable)1051 MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
1052 {
1053         module->load = gdk_pixbuf__tiff_image_load;
1054         module->begin_load = gdk_pixbuf__tiff_image_begin_load;
1055         module->stop_load = gdk_pixbuf__tiff_image_stop_load;
1056         module->load_increment = gdk_pixbuf__tiff_image_load_increment;
1057         module->save = gdk_pixbuf__tiff_image_save;
1058         module->save_to_callback = gdk_pixbuf__tiff_image_save_to_callback;
1059         module->is_save_option_supported = gdk_pixbuf__tiff_is_save_option_supported;
1060 }
1061 
MODULE_ENTRY(fill_info)1062 MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
1063 {
1064         static const GdkPixbufModulePattern signature[] = {
1065                 { "MM \x2a", "  z ", 100 },
1066                 { "II\x2a ", "   z", 100 },
1067                 { "II* \020   CR\002 ", "   z zzz   z", 0 },
1068                 { NULL, NULL, 0 }
1069         };
1070 	static const gchar *mime_types[] = {
1071 		"image/tiff",
1072 		NULL
1073 	};
1074 	static const gchar *extensions[] = {
1075 		"tiff",
1076 		"tif",
1077 		NULL
1078 	};
1079 
1080 	info->name = "tiff";
1081         info->signature = (GdkPixbufModulePattern *) signature;
1082 	info->description = NC_("image format", "TIFF");
1083 	info->mime_types = (gchar **) mime_types;
1084 	info->extensions = (gchar **) extensions;
1085 	info->flags = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
1086 	info->license = "LGPL";
1087 }
1088