From 8e6fd3390d2db2b0312fc3db4ea030c54e4aee05 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 16 Jun 2004 17:52:49 +0000 Subject: [PATCH] Make the tiff loader work with both libtiff 3.5.7 and libtiff 3.6.1. 2004-06-16 Matthias Clasen * io-tiff.c: Make the tiff loader work with both libtiff 3.5.7 and libtiff 3.6.1. (#135541, Marco Ghirlanda) --- gdk-pixbuf/ChangeLog | 5 ++ gdk-pixbuf/io-tiff.c | 155 ++++++++++++++++++++++++------------------- 2 files changed, 93 insertions(+), 67 deletions(-) diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 3a060d5426..a0cddd1add 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,8 @@ +2004-06-16 Matthias Clasen + + * io-tiff.c: Make the tiff loader work with both + libtiff 3.5.7 and libtiff 3.6.1. (#135541, Marco Ghirlanda) + Fri Jun 11 22:02:56 2004 Matthias Clasen * io-gif.c, io-pnm.c, io-tga.c, io-xpm.c: Don't use diff --git a/gdk-pixbuf/io-tiff.c b/gdk-pixbuf/io-tiff.c index 3ce8551a53..0acdd091da 100644 --- a/gdk-pixbuf/io-tiff.c +++ b/gdk-pixbuf/io-tiff.c @@ -145,34 +145,14 @@ static void free_buffer (guchar *pixels, gpointer data) g_free (pixels); } -static tileContigRoutine tiff_put_contig; -static tileSeparateRoutine tiff_put_separate; - -/* We're lucky that TIFFRGBAImage uses the same RGBA packing - as gdk-pixbuf, thus we can simple reuse the default libtiff - put routines, only adjusting the coordinate system. - */ -static void -put_contig (TIFFRGBAImage *img, uint32 *raster, - uint32 x, uint32 y, uint32 w, uint32 h, - int32 fromskew, int32 toskew, unsigned char *cp) +static gboolean tifflibversion (int *major, int *minor, int *revision) { - uint32 *data = raster - y * img->width - x; + if (sscanf (TIFFGetVersion(), + "LIBTIFF, Version %d.%d.%d", + major, minor, revision) < 3) + return FALSE; - tiff_put_contig (img, data + img->width * (img->height - 1 - y) + x, - x, y, w, h, fromskew, -toskew - 2*(int32)w, cp); -} - -static void -put_separate (TIFFRGBAImage *img, uint32 *raster, - uint32 x, uint32 y, uint32 w, uint32 h, - int32 fromskew, int32 toskew, - unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a) -{ - uint32 *data = raster - y * img->width - x; - - tiff_put_separate (img, data + img->width * (img->height - 1 - y) + x, - x, y, w, h, fromskew, -toskew - 2*w, r, g, b, a); + return TRUE; } static GdkPixbuf * @@ -181,8 +161,9 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error) guchar *pixels = NULL; gint width, height, rowstride, bytes; GdkPixbuf *pixbuf; - TIFFRGBAImage img; - gchar emsg[1024]; +#if TIFFLIB_VERSION >= 20031226 + gint major, minor, revision; +#endif /* We're called with the lock held. */ @@ -263,49 +244,89 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error) if (context) (* context->prepare_func) (pixbuf, NULL, context->user_data); G_LOCK (tiff_loader); - - if (!TIFFRGBAImageBegin (&img, tiff, 1, emsg) || global_error) { - tiff_set_error (error, - GDK_PIXBUF_ERROR_FAILED, - _("Failed to load RGB data from TIFF file")); - g_object_unref (pixbuf); - return NULL; - } - if (img.put.any == NULL) { - tiff_set_error (error, - GDK_PIXBUF_ERROR_FAILED, - _("Unsupported TIFF variant")); - g_object_unref (pixbuf); - return NULL; - } - - if (img.isContig) { - tiff_put_contig = img.put.contig; - img.put.contig = put_contig; - } - else { - tiff_put_separate = img.put.separate; - img.put.separate = put_separate; - } - - TIFFRGBAImageGet (&img, (uint32 *)pixels, width, height); - TIFFRGBAImageEnd (&img); +#if TIFFLIB_VERSION >= 20031226 + if (tifflibversion(&major, &minor, &revision) && major == 3 && + (minor > 6 || (minor == 6 && revision > 0))) { + if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32 *)pixels, ORIENTATION_TOPLEFT, 1) || global_error) + { + tiff_set_error (error, + GDK_PIXBUF_ERROR_FAILED, + _("Failed to load RGB data from TIFF file")); + g_object_unref (pixbuf); + return NULL; + } #if G_BYTE_ORDER == G_BIG_ENDIAN -/* Turns out that the packing used by TIFFRGBAImage depends on the host byte order... */ - while (pixels < pixbuf->pixels + bytes) { - uint32 pixel = *(uint32 *)pixels; - int r = TIFFGetR(pixel); - int g = TIFFGetG(pixel); - int b = TIFFGetB(pixel); - int a = TIFFGetA(pixel); - *pixels++ = r; - *pixels++ = g; - *pixels++ = b; - *pixels++ = a; - } + /* Turns out that the packing used by TIFFRGBAImage depends on + * the host byte order... + */ + while (pixels < pixbuf->pixels + bytes) { + uint32 pixel = *(uint32 *)pixels; + int r = TIFFGetR(pixel); + int g = TIFFGetG(pixel); + int b = TIFFGetB(pixel); + int a = TIFFGetA(pixel); + *pixels++ = r; + *pixels++ = g; + *pixels++ = b; + *pixels++ = a; + } #endif + } + else +#endif + { + uint32 *rast, *tmp_rast; + gint x, y; + guchar *tmppix; + + /* Yes, it needs to be _TIFFMalloc... */ + rast = (uint32 *) _TIFFmalloc (width * height * sizeof (uint32)); + if (!rast) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Insufficient memory to open TIFF file")); + g_object_unref (pixbuf); + + return NULL; + } + if (!TIFFReadRGBAImage (tiff, width, height, rast, 1) || global_error) { + tiff_set_error (error, + GDK_PIXBUF_ERROR_FAILED, + _("Failed to load RGB data from TIFF file")); + g_object_unref (pixbuf); + _TIFFfree (rast); + + return NULL; + } + + pixels = gdk_pixbuf_get_pixels (pixbuf); + + g_assert (pixels); + + tmppix = pixels; + + for (y = 0; y < height; y++) { + /* Unexplainable...are tiffs backwards? */ + /* Also looking at the GIMP plugin, this + * whole reading thing can be a bit more + * robust. + */ + tmp_rast = rast + ((height - y - 1) * width); + for (x = 0; x < width; x++) { + tmppix[0] = TIFFGetR (*tmp_rast); + tmppix[1] = TIFFGetG (*tmp_rast); + tmppix[2] = TIFFGetB (*tmp_rast); + tmppix[3] = TIFFGetA (*tmp_rast); + tmp_rast++; + tmppix += 4; + } + } + + _TIFFfree (rast); + } G_UNLOCK (tiff_loader); if (context)