Include a Other Software section in Help file
[geeqie.git] / src / image_load_tiff.c
index fd938b5..afc1822 100644 (file)
@@ -1,39 +1,28 @@
 /*
- * Geeqie
- * (C) 2004 John Ellis
- * Copyright (C) 2008 - 2011 The Geeqie Team
- *
- * Author: Vladimir Nadvornik
- *
- * This software is released under the GNU General Public License (GNU GPL).
- * Please read the included file COPYING for more information.
- * This software comes with no warranty of any kind, use at your own risk!
- */
-
-/* based on code from GdkPixbuf library - TIFF image loader
- *
  * Copyright (C) 1999 Mark Crichton
  * Copyright (C) 1999 The Free Software Foundation
+ * Copyright (C) 2004 John Ellis
+ * Copyright (C) 2008 - 2016 The Geeqie Team
  *
  * Authors: Mark Crichton <crichton@gimp.org>
  *          Federico Mena-Quintero <federico@gimp.org>
  *          Jonathan Blandford <jrb@redhat.com>
  *          S�ren Sandmann <sandmann@daimi.au.dk>
+ *         Vladimir Nadvornik
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include "main.h"
@@ -50,18 +39,20 @@ struct _ImageLoaderTiff {
        ImageLoaderBackendCbAreaUpdated area_updated_cb;
        ImageLoaderBackendCbSize size_cb;
        ImageLoaderBackendCbAreaPrepared area_prepared_cb;
-       
+
        gpointer data;
 
        GdkPixbuf *pixbuf;
        guint requested_width;
        guint requested_height;
-       
+
        gboolean abort;
 
        const guchar *buffer;
        toff_t used;
        toff_t pos;
+       gint page_num;
+       gint page_total;
 };
 
 static void free_buffer (guchar *pixels, gpointer data)
@@ -152,8 +143,10 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
 
        TIFF *tiff;
        guchar *pixels = NULL;
-       gint width, height, rowstride, bytes;
+       gint width, height, rowstride;
+       size_t bytes;
        uint32 rowsperstrip;
+       gint dircount = 0;
 
        lt->buffer = buf;
        lt->used = count;
@@ -171,7 +164,21 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
                DEBUG_1("Failed to open TIFF image");
                return FALSE;
                }
+       else
+               {
+               do
+                       {
+                       dircount++;
+                       } while (TIFFReadDirectory(tiff));
+               lt->page_total = dircount;
+               }
 
+    if (!TIFFSetDirectory(tiff, lt->page_num))
+               {
+               DEBUG_1("Failed to open TIFF image");
+               TIFFClose(tiff);
+               return FALSE;
+               }
 
        if (!TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width))
                {
@@ -197,15 +204,15 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
        rowstride = width * 4;
        if (rowstride / 4 != width)
                { /* overflow */
-               DEBUG_1("Dimensions of TIFF image too large");
+               DEBUG_1("Dimensions of TIFF image too large: width %d", width);
                TIFFClose(tiff);
                return FALSE;
                }
 
-       bytes = height * rowstride;
-       if (bytes / rowstride != height)
+       bytes = (size_t) height * rowstride;
+       if (bytes / rowstride != (size_t) height)
                { /* overflow */
-               DEBUG_1("Dimensions of TIFF image too large");
+               DEBUG_1("Dimensions of TIFF image too large: height %d", height);
                TIFFClose(tiff);
                return FALSE;
                }
@@ -218,7 +225,7 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
 
        if (!pixels)
                {
-               DEBUG_1("Insufficient memory to open TIFF file");
+               DEBUG_1("Insufficient memory to open TIFF file: need %zu", bytes);
                TIFFClose(tiff);
                return FALSE;
                }
@@ -239,13 +246,14 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
        if (TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
                {
                /* read by strip */
-               int row;
-               guchar *wrk_line = (guchar *)g_malloc(width * sizeof (uint32));
+               ptrdiff_t row;
+               const size_t line_bytes = width * sizeof(uint32);
+               guchar *wrk_line = (guchar *)g_malloc(line_bytes);
 
                for (row = 0; row < height; row += rowsperstrip)
                        {
                        int rows_to_write, i_row;
-                       
+
                        if (lt->abort) {
                                break;
                        }
@@ -274,9 +282,9 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
                                top_line = pixels + (row + i_row) * rowstride;
                                bottom_line = pixels + (row + rows_to_write - i_row - 1) * rowstride;
 
-                               memcpy(wrk_line, top_line, 4*width);
-                               memcpy(top_line, bottom_line, 4*width);
-                               memcpy(bottom_line, wrk_line, 4*width);
+                               memcpy(wrk_line, top_line, line_bytes);
+                               memcpy(top_line, bottom_line, line_bytes);
+                               memcpy(bottom_line, wrk_line, line_bytes);
                                }
                        lt->area_updated_cb(loader, 0, row, width, rows_to_write, lt->data);
                        }
@@ -295,18 +303,21 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
                /* Turns out that the packing used by TIFFRGBAImage depends on
                 * the host byte order...
                 */
-               while (pixels < lt->pixbuf->pixels + bytes)
+               {
+               guchar *ptr = pixels;
+               while (ptr < pixels + bytes)
                        {
-                       uint32 pixel = *(uint32 *)pixels;
+                       uint32 pixel = *(uint32 *)ptr;
                        int r = TIFFGetR(pixel);
                        int g = TIFFGetG(pixel);
                        int b = TIFFGetB(pixel);
                        int a = TIFFGetA(pixel);
-                       *pixels++ = r;
-                       *pixels++ = g;
-                       *pixels++ = b;
-                       *pixels++ = a;
+                       *ptr++ = r;
+                       *ptr++ = g;
+                       *ptr++ = b;
+                       *ptr++ = a;
                        }
+               }
 #endif
 
                lt->area_updated_cb(loader, 0, 0, width, height, lt->data);
@@ -370,6 +381,19 @@ static void image_loader_tiff_free(gpointer loader)
        g_free(lt);
 }
 
+static void image_loader_tiff_set_page_num(gpointer loader, gint page_num)
+{
+       ImageLoaderTiff *lt = (ImageLoaderTiff *) loader;
+
+       lt->page_num = page_num;
+}
+
+static gint image_loader_tiff_get_page_total(gpointer loader)
+{
+       ImageLoaderTiff *lt = (ImageLoaderTiff *) loader;
+
+       return lt->page_total;
+}
 
 void image_loader_backend_set_tiff(ImageLoaderBackend *funcs)
 {
@@ -381,9 +405,12 @@ void image_loader_backend_set_tiff(ImageLoaderBackend *funcs)
        funcs->close = image_loader_tiff_close;
        funcs->abort = image_loader_tiff_abort;
        funcs->free = image_loader_tiff_free;
-       
+
        funcs->get_format_name = image_loader_tiff_get_format_name;
        funcs->get_format_mime_types = image_loader_tiff_get_format_mime_types;
+
+       funcs->set_page_num = image_loader_tiff_set_page_num;
+       funcs->get_page_total = image_loader_tiff_get_page_total;
 }