IMG_tif.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 10 Nov 2009 06:00:59 +0000
changeset 237 d1a4fae44bd0
parent 236 cce1251de477
child 280 ec4ae96c100c
permissions -rw-r--r--
In the process of tracking down bug #868, made ImageIO the default for building using command line tools, and cleaned up the ImageIO image loading code.
slouken@0
     1
/*
slouken@53
     2
    SDL_image:  An example image loading library for use with SDL
slouken@186
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@121
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@121
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@121
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@121
    15
    You should have received a copy of the GNU Lesser General Public
slouken@121
    16
    License along with this library; if not, write to the Free Software
slouken@121
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@53
    20
    slouken@libsdl.org
slouken@53
    21
*/
slouken@0
    22
slouken@237
    23
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
slouken@237
    24
slouken@0
    25
/* This is a TIFF image file loading framework */
slouken@0
    26
slouken@0
    27
#include <stdio.h>
slouken@0
    28
slouken@0
    29
#include "SDL_image.h"
slouken@0
    30
slouken@0
    31
#ifdef LOAD_TIF
slouken@0
    32
slouken@0
    33
#include <tiffio.h>
slouken@0
    34
slouken@143
    35
static struct {
slouken@143
    36
	int loaded;
slouken@143
    37
	void *handle;
slouken@143
    38
	TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
slouken@143
    39
	void (*TIFFClose)(TIFF*);
slouken@143
    40
	int (*TIFFGetField)(TIFF*, ttag_t, ...);
slouken@143
    41
	int (*TIFFReadRGBAImage)(TIFF*, uint32, uint32, uint32*, int);
slouken@143
    42
	TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
slouken@143
    43
} lib;
slouken@143
    44
slouken@143
    45
#ifdef LOAD_TIF_DYNAMIC
slouken@205
    46
int IMG_InitTIF()
slouken@143
    47
{
slouken@143
    48
	if ( lib.loaded == 0 ) {
slouken@143
    49
		lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
slouken@143
    50
		if ( lib.handle == NULL ) {
slouken@143
    51
			return -1;
slouken@143
    52
		}
slouken@143
    53
		lib.TIFFClientOpen =
slouken@143
    54
			(TIFF* (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
slouken@143
    55
			SDL_LoadFunction(lib.handle, "TIFFClientOpen");
slouken@143
    56
		if ( lib.TIFFClientOpen == NULL ) {
slouken@143
    57
			SDL_UnloadObject(lib.handle);
slouken@143
    58
			return -1;
slouken@143
    59
		}
slouken@143
    60
		lib.TIFFClose =
slouken@143
    61
			(void (*)(TIFF*))
slouken@143
    62
			SDL_LoadFunction(lib.handle, "TIFFClose");
slouken@143
    63
		if ( lib.TIFFClose == NULL ) {
slouken@143
    64
			SDL_UnloadObject(lib.handle);
slouken@143
    65
			return -1;
slouken@143
    66
		}
slouken@143
    67
		lib.TIFFGetField =
slouken@143
    68
			(int (*)(TIFF*, ttag_t, ...))
slouken@143
    69
			SDL_LoadFunction(lib.handle, "TIFFGetField");
slouken@143
    70
		if ( lib.TIFFGetField == NULL ) {
slouken@143
    71
			SDL_UnloadObject(lib.handle);
slouken@143
    72
			return -1;
slouken@143
    73
		}
slouken@143
    74
		lib.TIFFReadRGBAImage =
slouken@143
    75
			(int (*)(TIFF*, uint32, uint32, uint32*, int))
slouken@143
    76
			SDL_LoadFunction(lib.handle, "TIFFReadRGBAImage");
slouken@143
    77
		if ( lib.TIFFReadRGBAImage == NULL ) {
slouken@143
    78
			SDL_UnloadObject(lib.handle);
slouken@143
    79
			return -1;
slouken@143
    80
		}
slouken@143
    81
		lib.TIFFSetErrorHandler =
slouken@143
    82
			(TIFFErrorHandler (*)(TIFFErrorHandler))
slouken@143
    83
			SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler");
slouken@143
    84
		if ( lib.TIFFSetErrorHandler == NULL ) {
slouken@143
    85
			SDL_UnloadObject(lib.handle);
slouken@143
    86
			return -1;
slouken@143
    87
		}
slouken@143
    88
	}
slouken@143
    89
	++lib.loaded;
slouken@143
    90
slouken@143
    91
	return 0;
slouken@143
    92
}
slouken@205
    93
void IMG_QuitTIF()
slouken@143
    94
{
slouken@143
    95
	if ( lib.loaded == 0 ) {
slouken@143
    96
		return;
slouken@143
    97
	}
slouken@143
    98
	if ( lib.loaded == 1 ) {
slouken@143
    99
		SDL_UnloadObject(lib.handle);
slouken@143
   100
	}
slouken@143
   101
	--lib.loaded;
slouken@143
   102
}
slouken@143
   103
#else
slouken@205
   104
int IMG_InitTIF()
slouken@143
   105
{
slouken@143
   106
	if ( lib.loaded == 0 ) {
slouken@143
   107
		lib.TIFFClientOpen = TIFFClientOpen;
slouken@143
   108
		lib.TIFFClose = TIFFClose;
slouken@143
   109
		lib.TIFFGetField = TIFFGetField;
slouken@143
   110
		lib.TIFFReadRGBAImage = TIFFReadRGBAImage;
slouken@143
   111
		lib.TIFFSetErrorHandler = TIFFSetErrorHandler;
slouken@143
   112
	}
slouken@143
   113
	++lib.loaded;
slouken@146
   114
slouken@146
   115
	return 0;
slouken@143
   116
}
slouken@205
   117
void IMG_QuitTIF()
slouken@143
   118
{
slouken@143
   119
	if ( lib.loaded == 0 ) {
slouken@143
   120
		return;
slouken@143
   121
	}
slouken@143
   122
	if ( lib.loaded == 1 ) {
slouken@143
   123
	}
slouken@143
   124
	--lib.loaded;
slouken@143
   125
}
slouken@143
   126
#endif /* LOAD_TIF_DYNAMIC */
slouken@143
   127
slouken@0
   128
/*
slouken@0
   129
 * These are the thunking routine to use the SDL_RWops* routines from
slouken@0
   130
 * libtiff's internals.
slouken@0
   131
*/
slouken@0
   132
slouken@0
   133
static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
   134
{
slouken@0
   135
	return SDL_RWread((SDL_RWops*)fd, buf, 1, size);
slouken@0
   136
}
slouken@0
   137
slouken@0
   138
static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
slouken@0
   139
{
slouken@0
   140
	return SDL_RWseek((SDL_RWops*)fd, offset, origin);
slouken@0
   141
}
slouken@0
   142
slouken@0
   143
static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
   144
{
slouken@0
   145
	return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
slouken@0
   146
}
slouken@0
   147
slouken@0
   148
static int tiff_close(thandle_t fd)
slouken@0
   149
{
slouken@0
   150
	/*
slouken@0
   151
	 * We don't want libtiff closing our SDL_RWops*, but if it's not given
slouken@0
   152
         * a routine to try, and if the image isn't a TIFF, it'll segfault.
slouken@0
   153
	 */
slouken@0
   154
	return 0;
slouken@0
   155
}
slouken@0
   156
slouken@167
   157
static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
slouken@167
   158
{
slouken@167
   159
	return (0);
slouken@167
   160
}
slouken@167
   161
slouken@167
   162
static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
slouken@167
   163
{
slouken@167
   164
	return;
slouken@167
   165
}
slouken@167
   166
slouken@0
   167
static toff_t tiff_size(thandle_t fd)
slouken@0
   168
{
slouken@0
   169
	Uint32 save_pos;
slouken@0
   170
	toff_t size;
slouken@0
   171
slouken@0
   172
	save_pos = SDL_RWtell((SDL_RWops*)fd);
slouken@236
   173
	SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END);
slouken@0
   174
        size = SDL_RWtell((SDL_RWops*)fd);
slouken@236
   175
	SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET);
slouken@0
   176
	return size;
slouken@0
   177
}
slouken@0
   178
slouken@0
   179
int IMG_isTIF(SDL_RWops* src)
slouken@0
   180
{
slouken@117
   181
	int start;
slouken@117
   182
	int is_TIF;
slouken@167
   183
	Uint8 magic[4];
slouken@0
   184
icculus@154
   185
	if ( !src )
icculus@154
   186
		return 0;
slouken@117
   187
	start = SDL_RWtell(src);
slouken@117
   188
	is_TIF = 0;
slouken@167
   189
	if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
slouken@167
   190
		if ( (magic[0] == 'I' &&
slouken@167
   191
                      magic[1] == 'I' &&
slouken@167
   192
		      magic[2] == 0x2a &&
slouken@167
   193
                      magic[3] == 0x00) ||
slouken@167
   194
		     (magic[0] == 'M' &&
slouken@167
   195
                      magic[1] == 'M' &&
slouken@167
   196
		      magic[2] == 0x00 &&
slouken@167
   197
                      magic[3] == 0x2a) ) {
slouken@167
   198
			is_TIF = 1;
slouken@167
   199
		}
slouken@117
   200
	}
slouken@236
   201
	SDL_RWseek(src, start, RW_SEEK_SET);
slouken@117
   202
	return(is_TIF);
slouken@0
   203
}
slouken@0
   204
slouken@0
   205
SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
slouken@0
   206
{
slouken@118
   207
	int start;
slouken@0
   208
	TIFF* tiff;
slouken@0
   209
	SDL_Surface* surface = NULL;
slouken@0
   210
	Uint32 img_width, img_height;
slouken@145
   211
	Uint32 Rmask, Gmask, Bmask, Amask;
slouken@0
   212
	Uint32 x, y;
slouken@0
   213
	Uint32 half;
slouken@0
   214
slouken@98
   215
	if ( !src ) {
slouken@98
   216
		/* The error message has been set in SDL_RWFromFile */
slouken@98
   217
		return NULL;
slouken@98
   218
	}
slouken@118
   219
	start = SDL_RWtell(src);
slouken@0
   220
slouken@233
   221
	if ( !IMG_Init(IMG_INIT_TIF) ) {
slouken@143
   222
		return NULL;
slouken@143
   223
	}
slouken@143
   224
slouken@0
   225
	/* turn off memory mapped access with the m flag */
slouken@143
   226
	tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src, 
slouken@167
   227
		tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
slouken@0
   228
	if(!tiff)
slouken@118
   229
		goto error;
slouken@0
   230
slouken@0
   231
	/* Retrieve the dimensions of the image from the TIFF tags */
slouken@143
   232
	lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
slouken@143
   233
	lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
slouken@0
   234
slouken@4
   235
	Rmask = 0x000000FF;
slouken@4
   236
	Gmask = 0x0000FF00;
slouken@4
   237
	Bmask = 0x00FF0000;
slouken@4
   238
	Amask = 0xFF000000;
slouken@0
   239
	surface = SDL_AllocSurface(SDL_SWSURFACE, img_width, img_height, 32,
slouken@0
   240
		Rmask, Gmask, Bmask, Amask);
slouken@0
   241
	if(!surface)
slouken@118
   242
		goto error;
slouken@0
   243
	
slouken@143
   244
	if(!lib.TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0))
slouken@118
   245
		goto error;
slouken@0
   246
slouken@4
   247
	/* libtiff loads the image upside-down, flip it back */
slouken@0
   248
	half = img_height / 2;
slouken@4
   249
	for(y = 0; y < half; y++)
slouken@0
   250
	{
slouken@4
   251
	        Uint32 *top = (Uint32 *)surface->pixels + y * surface->pitch/4;
slouken@4
   252
	        Uint32 *bot = (Uint32 *)surface->pixels
slouken@4
   253
		              + (img_height - y - 1) * surface->pitch/4;
slouken@0
   254
		for(x = 0; x < img_width; x++)
slouken@0
   255
		{
slouken@4
   256
		        Uint32 tmp = top[x];
slouken@4
   257
			top[x] = bot[x];
slouken@4
   258
			bot[x] = tmp;
slouken@0
   259
		}
slouken@0
   260
	}
slouken@143
   261
	lib.TIFFClose(tiff);
slouken@0
   262
	
slouken@0
   263
	return surface;
slouken@118
   264
slouken@118
   265
error:
slouken@236
   266
	SDL_RWseek(src, start, RW_SEEK_SET);
slouken@118
   267
	if ( surface ) {
slouken@118
   268
		SDL_FreeSurface(surface);
slouken@118
   269
	}
slouken@118
   270
	return NULL;
slouken@0
   271
}
slouken@0
   272
slouken@0
   273
#else
slouken@0
   274
slouken@205
   275
int IMG_InitTIF()
slouken@205
   276
{
slouken@205
   277
	IMG_SetError("TIFF images are not supported");
slouken@205
   278
	return(-1);
slouken@205
   279
}
slouken@205
   280
slouken@205
   281
void IMG_QuitTIF()
slouken@205
   282
{
slouken@205
   283
}
slouken@205
   284
slouken@0
   285
/* See if an image is contained in a data source */
slouken@0
   286
int IMG_isTIF(SDL_RWops *src)
slouken@0
   287
{
slouken@0
   288
	return(0);
slouken@0
   289
}
slouken@0
   290
slouken@0
   291
/* Load a TIFF type image from an SDL datasource */
slouken@0
   292
SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
slouken@0
   293
{
slouken@0
   294
	return(NULL);
slouken@0
   295
}
slouken@0
   296
slouken@0
   297
#endif /* LOAD_TIF */
slouken@237
   298
slouken@237
   299
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */