--- io-tiff.c.orig Tue Jul 17 05:00:19 2007 +++ io-tiff.c Wed Sep 11 10:28:58 2013 @@ -141,27 +141,14 @@ g_free (pixels); } -#if TIFFLIB_VERSION >= 20031226 -static gboolean tifflibversion (int *major, int *minor, int *revision) -{ - if (sscanf (TIFFGetVersion(), - "LIBTIFF, Version %d.%d.%d", - major, minor, revision) < 3) - return FALSE; - - return TRUE; -} -#endif - static GdkPixbuf * tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error) { guchar *pixels = NULL; gint width, height, rowstride, bytes; GdkPixbuf *pixbuf; -#if TIFFLIB_VERSION >= 20031226 - gint major, minor, revision; -#endif + uint16 orientation = 0; + uint16 transform = 0; /* We're called with the lock held. */ @@ -211,14 +198,15 @@ gint w = width; gint h = height; (* context->size_func) (&w, &h, context->user_data); - /* This is a signal that this function is being called - to support gdk_pixbuf_get_file_info, so we can stop - parsing the tiff file at this point. It is not an - error condition. */ - - if (w == 0 || h == 0) + + /* This is a signal that this function is being called + to support gdk_pixbuf_get_file_info, so we can stop + parsing the tiff file at this point. It is not an + error condition. */ + + if (w == 0 || h == 0) return NULL; - } + } pixels = g_try_malloc (bytes); @@ -242,95 +230,73 @@ return NULL; } + /* Set the "orientation" key associated with this image. libtiff + orientation handling is odd, so further processing is required + by higher-level functions based on this tag. If the embedded + orientation tag is 1-4, libtiff flips/mirrors the image as + required, and no client processing is required - so we report + no orientation. Orientations 5-8 require rotations which would + swap the width and height of the image. libtiff does not do this. + Instead it interprets orientations 5-8 the same as 1-4. + See http://bugzilla.remotesensing.org/show_bug.cgi?id=1548. + To correct for this, the client must apply the transform normally + used for orientation 5 to both orientations 5 and 7, and apply + the transform normally used for orientation 7 for both + orientations 6 and 8. Then everythings works out OK! */ + + TIFFGetField (tiff, TIFFTAG_ORIENTATION, &orientation); + + switch (orientation) { + case 5: + case 7: + transform = 5; + break; + case 6: + case 8: + transform = 7; + break; + default: + transform = 0; + break; + } + + if (transform > 0 ) { + gchar str[5]; + snprintf (str, sizeof (str), "%d", transform); + gdk_pixbuf_set_option (pixbuf, "orientation", str); + } + if (context && context->prepare_func) (* context->prepare_func) (pixbuf, NULL, context->user_data); -#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 (!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; - } -#endif - } - else + /* 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 - { - 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); - } if (context && context->update_func) (* context->update_func) (pixbuf, 0, 0, width, height, context->user_data); - + return pixbuf; } @@ -434,7 +400,7 @@ switch (whence) { case SEEK_SET: - if (offset > context->used || offset < 0) + if (offset > context->used) return -1; context->pos = offset; break; @@ -450,7 +416,6 @@ break; default: return -1; - break; } return context->pos; } @@ -626,8 +591,6 @@ switch (whence) { case SEEK_SET: - if (offset < 0) - return -1; context->pos = offset; break; case SEEK_CUR: @@ -638,7 +601,6 @@ break; default: return -1; - break; } return context->pos; } @@ -831,6 +793,7 @@ static GdkPixbufModulePattern signature[] = { { "MM \x2a", " z ", 100 }, { "II\x2a ", " z", 100 }, + { "II* \020 CR\002 ", " z zzz z", 0 }, { NULL, NULL, 0 } }; static gchar * mime_types[] = {