io-tiff.c 18.5 KB
Newer Older
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 6 7 8
 * Copyright (C) 1999 The Free Software Foundation
 *
 * Authors: Mark Crichton <crichton@gimp.org>
 *          Federico Mena-Quintero <federico@gimp.org>
9
 *          Jonathan Blandford <jrb@redhat.com>
10
 *          Sren Sandmann <sandmann@daimi.au.dk>
11 12
 *
 * This library is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU Lesser General Public
14 15 16 17 18 19
 * 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,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20
 * Lesser General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Lesser General Public
23 24 25
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
26 27 28 29 30
 */

/* Following code (almost) blatantly ripped from Imlib */

#include <config.h>
31 32
#include <stdlib.h>
#include <string.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
33
#ifdef HAVE_UNISTD_H
34
#include <unistd.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
35
#endif
36
#include <tiffio.h>
37
#include <errno.h>
38
#include "gdk-pixbuf-private.h"
39
#include "gdk-pixbuf-io.h"
40

Tor Lillqvist's avatar
Tor Lillqvist committed
41 42
#ifdef G_OS_WIN32
#include <fcntl.h>
43 44
#include <io.h>
#define lseek(a,b,c) _lseek(a,b,c)
Tor Lillqvist's avatar
Tor Lillqvist committed
45 46
#define O_RDWR _O_RDWR
#endif
47 48


49 50
typedef struct _TiffContext TiffContext;
struct _TiffContext
51
{
52
	GdkPixbufModuleSizeFunc size_func;
53 54
	GdkPixbufModulePreparedFunc prepare_func;
	GdkPixbufModuleUpdatedFunc update_func;
55
	gpointer user_data;
56 57 58 59 60
        
        guchar *buffer;
        guint allocated;
        guint used;
        guint pos;
61 62 63
};


64

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
static char *global_error = NULL;
static TIFFErrorHandler orig_error_handler = NULL;
static TIFFErrorHandler orig_warning_handler = NULL;

static void
tiff_warning_handler (const char *mod, const char *fmt, va_list ap)
{
        /* Don't print anything; we should not be dumping junk to
         * stderr, since that may be bad for some apps.
         */

        /* libTIFF seems to occasionally warn about things that
         * are really errors, so maybe we should just call tiff_error_handler
         * here.
         */
}

static void
tiff_error_handler (const char *mod, const char *fmt, va_list ap)
{
        if (global_error) {                
                /* Blah, loader called us twice */
                return;
        }

        global_error = g_strdup_vprintf (fmt, ap);
}

static void
tiff_push_handlers (void)
{
        if (global_error)
                g_warning ("TIFF loader left crufty global_error around, FIXME");
        
        orig_error_handler = TIFFSetErrorHandler (tiff_error_handler);
        orig_warning_handler = TIFFSetWarningHandler (tiff_warning_handler);
}

static void
tiff_pop_handlers (void)
{
        if (global_error)
                g_warning ("TIFF loader left crufty global_error around, FIXME");
        
        TIFFSetErrorHandler (orig_error_handler);
        TIFFSetWarningHandler (orig_warning_handler);
}

static void
tiff_set_error (GError    **error,
                int         error_code,
                const char *msg)
{
        /* Take the error message from libtiff and merge it with
         * some context we provide.
         */
        if (global_error) {
122 123 124 125 126
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             error_code,
                             "%s%s%s", msg, ": ", global_error);

127 128 129
                g_free (global_error);
                global_error = NULL;
        }
130 131 132 133 134
        else {
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             error_code, msg);
        }
135 136 137 138
}



139 140 141 142 143
static void free_buffer (guchar *pixels, gpointer data)
{
	g_free (pixels);
}

144
#if TIFFLIB_VERSION >= 20031226
145
static gboolean tifflibversion (int *major, int *minor, int *revision)
146
{
147 148 149 150
        if (sscanf (TIFFGetVersion(), 
                    "LIBTIFF, Version %d.%d.%d", 
                    major, minor, revision) < 3)
                return FALSE;
151

152
        return TRUE;
153
}
154
#endif
155

156
static GdkPixbuf *
157
tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
158
{
159
	guchar *pixels = NULL;
160
	gint width, height, rowstride, bytes;
161
	GdkPixbuf *pixbuf;
162 163 164
#if TIFFLIB_VERSION >= 20031226
        gint major, minor, revision;
#endif
165

166 167 168 169
        /* We're called with the lock held. */
        
        g_return_val_if_fail (global_error == NULL, NULL);

170
	if (!TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width) || global_error) {
171 172 173 174 175 176
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_FAILED,
                                _("Could not get image width (bad TIFF file)"));
                return NULL;
        }
        
177
        if (!TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height) || global_error) {
178 179 180 181 182 183
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_FAILED,
                                _("Could not get image height (bad TIFF file)"));
                return NULL;
        }

184
        if (width <= 0 || height <= 0) {
185 186 187
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
188 189
                             _("Width or height of TIFF image is zero"));
                return NULL;                
190
        }
191
        
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
        rowstride = width * 4;
        if (rowstride / 4 != width) { /* overflow */
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                             _("Dimensions of TIFF image too large"));
                return NULL;                
        }
        
        bytes = height * rowstride;
        if (bytes / rowstride != height) { /* overflow */
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                             _("Dimensions of TIFF image too large"));
                return NULL;                
        }

210 211 212 213 214 215 216 217 218
	if (context && context->size_func) {
                gint w = width;
                gint h = height;
		(* context->size_func) (&w, &h, context->user_data);
                
                if (w == 0 || h == 0)
                    return NULL;
        }

219 220 221
        pixels = g_try_malloc (bytes);

        if (!pixels) {
222 223 224 225
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                             _("Insufficient memory to open TIFF file"));
226
                return NULL;
227
        }
228

229 230 231 232 233
	pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
                                           width, height, rowstride,
                                           free_buffer, NULL);
        if (!pixbuf) {
                g_free (pixels);
234 235 236 237
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                             _("Insufficient memory to open TIFF file"));
238
                return NULL;
239 240 241 242
        }

	if (context)
		(* context->prepare_func) (pixbuf, NULL, context->user_data);
243

244 245 246 247 248 249 250 251 252 253 254
#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;
                }
255

256
#if G_BYTE_ORDER == G_BIG_ENDIAN
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
                /* 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
Matthias Clasen's avatar
Matthias Clasen committed
272
        }
273
        else 
Matthias Clasen's avatar
Matthias Clasen committed
274
#endif
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
              {
                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);
             }
Matthias Clasen's avatar
Matthias Clasen committed
326

327
	if (context)
328
		(* context->update_func) (pixbuf, 0, 0, width, height, context->user_data);
329 330
        
        return pixbuf;
331
}
332

333

334

335
/* Static loader */
336

337 338
static GdkPixbuf *
gdk_pixbuf__tiff_image_load (FILE *f, GError **error)
339
{
340 341 342 343 344 345 346 347 348
        TIFF *tiff;
        int fd;
        GdkPixbuf *pixbuf;
        
        g_return_val_if_fail (f != NULL, NULL);

        tiff_push_handlers ();
        
        fd = fileno (f);
349 350 351 352 353 354 355

        /* On OSF, apparently fseek() works in some on-demand way, so
         * the fseek gdk_pixbuf_new_from_file() doesn't work here
         * since we are using the raw file descriptor. So, we call lseek() on the fd
         * before using it. (#60840)
         */
        lseek (fd, 0, SEEK_SET);
356 357
        tiff = TIFFFdOpen (fd, "libpixbuf-tiff", "r");
        
358 359 360 361
        if (!tiff || global_error) {
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                _("Failed to open TIFF image"));
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
                tiff_pop_handlers ();

                return NULL;
        }

        pixbuf = tiff_image_parse (tiff, NULL, error);
        
        TIFFClose (tiff);
        if (global_error) {
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_FAILED,
                                _("TIFFClose operation failed"));
        }
        
        tiff_pop_handlers ();

        return pixbuf;
379
}
380

381 382 383


/* Progressive loader */
384

385
static gpointer
386 387 388
gdk_pixbuf__tiff_image_begin_load (GdkPixbufModuleSizeFunc size_func,
                                   GdkPixbufModulePreparedFunc prepare_func,
				   GdkPixbufModuleUpdatedFunc update_func,
Havoc Pennington's avatar
Havoc Pennington committed
389 390
				   gpointer user_data,
                                   GError **error)
391
{
392 393 394
	TiffContext *context;
        
	context = g_new0 (TiffContext, 1);
395
	context->size_func = size_func;
396
	context->prepare_func = prepare_func;
Jonathan Blandford's avatar
Jonathan Blandford committed
397
	context->update_func = update_func;
398
	context->user_data = user_data;
399 400 401 402 403 404 405
        context->buffer = NULL;
        context->allocated = 0;
        context->used = 0;
        context->pos = 0;
        
	return context;
}
406

407 408 409 410 411 412 413 414 415 416 417 418
static tsize_t
tiff_read (thandle_t handle, tdata_t buf, tsize_t size)
{
        TiffContext *context = (TiffContext *)handle;
        
        if (context->pos + size > context->used)
                return 0;
        
        memcpy (buf, context->buffer + context->pos, size);
        context->pos += size;
        return size;
}
419

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
static tsize_t
tiff_write (thandle_t handle, tdata_t buf, tsize_t size)
{
        return -1;
}

static toff_t
tiff_seek (thandle_t handle, toff_t offset, int whence)
{
        TiffContext *context = (TiffContext *)handle;
        
        switch (whence) {
        case SEEK_SET:
                if (offset > context->used || offset < 0)
                        return -1;
                context->pos = offset;
                break;
        case SEEK_CUR:
                if (offset + context->pos >= context->used)
                        return -1;
                context->pos += offset;
                break;
        case SEEK_END:
                if (offset + context->used > context->used)
                        return -1;
                context->pos = context->used + offset;
                break;
        default:
                return -1;
                break;
        }
        return context->pos;
}

static int
tiff_close (thandle_t context)
{
        return 0;
}

static toff_t
tiff_size (thandle_t handle)
{
        TiffContext *context = (TiffContext *)handle;
        
        return context->used;
}

static int
tiff_map_file (thandle_t handle, tdata_t *buf, toff_t *size)
{
        TiffContext *context = (TiffContext *)handle;
        
        *buf = context->buffer;
        *size = context->used;
        
        return 0;
}

static void
tiff_unmap_file (thandle_t handle, tdata_t data, toff_t offset)
{
482 483
}

484 485 486
static gboolean
gdk_pixbuf__tiff_image_stop_load (gpointer data,
                                  GError **error)
487
{
488 489 490
        TiffContext *context = data;
        TIFF *tiff;
        gboolean retval;
491
        
492
        g_return_val_if_fail (data != NULL, FALSE);
493

494 495 496 497 498 499 500
        tiff_push_handlers ();
        
        tiff = TIFFClientOpen ("libtiff-pixbuf", "r", data, 
                               tiff_read, tiff_write, 
                               tiff_seek, tiff_close, 
                               tiff_size, 
                               tiff_map_file, tiff_unmap_file);
501 502 503 504
        if (!tiff || global_error) {
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_FAILED,
                                _("Failed to load TIFF image"));
505 506
                retval = FALSE;
        } else {
507
                GdkPixbuf *pixbuf;
508 509 510
                
                pixbuf = tiff_image_parse (tiff, context, error);
                if (pixbuf)
511
                        g_object_unref (pixbuf);
512
                retval = pixbuf != NULL;
513 514 515 516 517
                if (global_error)
                        {
                                tiff_set_error (error,
                                                GDK_PIXBUF_ERROR_FAILED,
                                                _("Failed to load TIFF image"));
518 519
                                tiff_pop_handlers ();

520 521
                                retval = FALSE;
                        }
522
        }
523

524 525 526
        if (tiff)
                TIFFClose (tiff);

527
        g_assert (!global_error);
528 529 530 531 532
        
        g_free (context->buffer);
        g_free (context);

        tiff_pop_handlers ();
533

534 535
        return retval;
}
536

537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
static gboolean
make_available_at_least (TiffContext *context, guint needed)
{
        guchar *new_buffer = NULL;
        guint need_alloc;
        
        need_alloc = context->used + needed;
        if (need_alloc > context->allocated) {
                guint new_size = 1;
                while (new_size < need_alloc)
                        new_size *= 2;
                
                new_buffer = g_try_realloc (context->buffer, new_size);
                if (new_buffer) {
                        context->buffer = new_buffer;
                        context->allocated = new_size;
                        return TRUE;
                }
                return FALSE;
        }
557
        return TRUE;
558 559
}

560 561 562
static gboolean
gdk_pixbuf__tiff_image_load_increment (gpointer data, const guchar *buf,
                                       guint size, GError **error)
563
{
564 565
	TiffContext *context = (TiffContext *) data;
        
566
	g_return_val_if_fail (data != NULL, FALSE);
567 568
        
        if (!make_available_at_least (context, size)) {
569
                g_set_error (error,
570 571 572 573 574 575 576 577
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                             _("Insufficient memory to open TIFF file"));
                return FALSE;
        }
        
        memcpy (context->buffer + context->used, buf, size);
        context->used += size;
578 579
	return TRUE;
}
580

581
void
582
MODULE_ENTRY (tiff, fill_vtable) (GdkPixbufModule *module)
583
{
584 585 586 587
        module->load = gdk_pixbuf__tiff_image_load;
        module->begin_load = gdk_pixbuf__tiff_image_begin_load;
        module->stop_load = gdk_pixbuf__tiff_image_stop_load;
        module->load_increment = gdk_pixbuf__tiff_image_load_increment;
588
}
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612

void
MODULE_ENTRY (tiff, fill_info) (GdkPixbufFormat *info)
{
        static GdkPixbufModulePattern signature[] = {
                { "MM \x2a", "  z ", 100 },
                { "II\x2a ", "   z", 100 },
                { NULL, NULL, 0 }
        };
	static gchar * mime_types[] = {
		"image/tiff",
		NULL
	};
	static gchar * extensions[] = {
		"tiff",
		"tif",
		NULL
	};

	info->name = "tiff";
        info->signature = signature;
	info->description = N_("The TIFF image format");
	info->mime_types = mime_types;
	info->extensions = extensions;
613
        /* not threadsafe, due the the error handler handling */
614
	info->flags = 0;
615
	info->license = "LGPL";
616
}