IMG_tif.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 28 Jan 2012 10:51:24 -0500
changeset 326 fa6129ca8503
parent 320 aa5d55b11751
child 343 5bf0f0d6a74e
permissions -rw-r--r--
Fixed SDL_image header location
slouken@0
     1
/*
slouken@280
     2
  SDL_image:  An example image loading library for use with SDL
slouken@280
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@280
     5
  This software is provided 'as-is', without any express or implied
slouken@280
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@280
     7
  arising from the use of this software.
slouken@0
     8
slouken@280
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@280
    10
  including commercial applications, and to alter it and redistribute it
slouken@280
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@280
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@280
    14
     claim that you wrote the original software. If you use this software
slouken@280
    15
     in a product, an acknowledgment in the product documentation would be
slouken@280
    16
     appreciated but is not required.
slouken@280
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@280
    18
     misrepresented as being the original software.
slouken@280
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@53
    20
*/
slouken@0
    21
slouken@237
    22
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
slouken@237
    23
slouken@0
    24
/* This is a TIFF image file loading framework */
slouken@0
    25
slouken@0
    26
#include <stdio.h>
slouken@0
    27
slouken@0
    28
#include "SDL_image.h"
slouken@0
    29
slouken@0
    30
#ifdef LOAD_TIF
slouken@0
    31
slouken@0
    32
#include <tiffio.h>
slouken@0
    33
slouken@143
    34
static struct {
slouken@143
    35
	int loaded;
slouken@143
    36
	void *handle;
slouken@143
    37
	TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
slouken@143
    38
	void (*TIFFClose)(TIFF*);
slouken@143
    39
	int (*TIFFGetField)(TIFF*, ttag_t, ...);
slouken@143
    40
	int (*TIFFReadRGBAImage)(TIFF*, uint32, uint32, uint32*, int);
slouken@143
    41
	TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
slouken@143
    42
} lib;
slouken@143
    43
slouken@143
    44
#ifdef LOAD_TIF_DYNAMIC
slouken@205
    45
int IMG_InitTIF()
slouken@143
    46
{
slouken@143
    47
	if ( lib.loaded == 0 ) {
slouken@143
    48
		lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
slouken@143
    49
		if ( lib.handle == NULL ) {
slouken@143
    50
			return -1;
slouken@143
    51
		}
slouken@143
    52
		lib.TIFFClientOpen =
slouken@143
    53
			(TIFF* (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
slouken@143
    54
			SDL_LoadFunction(lib.handle, "TIFFClientOpen");
slouken@143
    55
		if ( lib.TIFFClientOpen == NULL ) {
slouken@143
    56
			SDL_UnloadObject(lib.handle);
slouken@143
    57
			return -1;
slouken@143
    58
		}
slouken@143
    59
		lib.TIFFClose =
slouken@143
    60
			(void (*)(TIFF*))
slouken@143
    61
			SDL_LoadFunction(lib.handle, "TIFFClose");
slouken@143
    62
		if ( lib.TIFFClose == NULL ) {
slouken@143
    63
			SDL_UnloadObject(lib.handle);
slouken@143
    64
			return -1;
slouken@143
    65
		}
slouken@143
    66
		lib.TIFFGetField =
slouken@143
    67
			(int (*)(TIFF*, ttag_t, ...))
slouken@143
    68
			SDL_LoadFunction(lib.handle, "TIFFGetField");
slouken@143
    69
		if ( lib.TIFFGetField == NULL ) {
slouken@143
    70
			SDL_UnloadObject(lib.handle);
slouken@143
    71
			return -1;
slouken@143
    72
		}
slouken@143
    73
		lib.TIFFReadRGBAImage =
slouken@143
    74
			(int (*)(TIFF*, uint32, uint32, uint32*, int))
slouken@143
    75
			SDL_LoadFunction(lib.handle, "TIFFReadRGBAImage");
slouken@143
    76
		if ( lib.TIFFReadRGBAImage == NULL ) {
slouken@143
    77
			SDL_UnloadObject(lib.handle);
slouken@143
    78
			return -1;
slouken@143
    79
		}
slouken@143
    80
		lib.TIFFSetErrorHandler =
slouken@143
    81
			(TIFFErrorHandler (*)(TIFFErrorHandler))
slouken@143
    82
			SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler");
slouken@143
    83
		if ( lib.TIFFSetErrorHandler == NULL ) {
slouken@143
    84
			SDL_UnloadObject(lib.handle);
slouken@143
    85
			return -1;
slouken@143
    86
		}
slouken@143
    87
	}
slouken@143
    88
	++lib.loaded;
slouken@143
    89
slouken@143
    90
	return 0;
slouken@143
    91
}
slouken@205
    92
void IMG_QuitTIF()
slouken@143
    93
{
slouken@143
    94
	if ( lib.loaded == 0 ) {
slouken@143
    95
		return;
slouken@143
    96
	}
slouken@143
    97
	if ( lib.loaded == 1 ) {
slouken@143
    98
		SDL_UnloadObject(lib.handle);
slouken@143
    99
	}
slouken@143
   100
	--lib.loaded;
slouken@143
   101
}
slouken@143
   102
#else
slouken@205
   103
int IMG_InitTIF()
slouken@143
   104
{
slouken@143
   105
	if ( lib.loaded == 0 ) {
slouken@143
   106
		lib.TIFFClientOpen = TIFFClientOpen;
slouken@143
   107
		lib.TIFFClose = TIFFClose;
slouken@143
   108
		lib.TIFFGetField = TIFFGetField;
slouken@143
   109
		lib.TIFFReadRGBAImage = TIFFReadRGBAImage;
slouken@143
   110
		lib.TIFFSetErrorHandler = TIFFSetErrorHandler;
slouken@143
   111
	}
slouken@143
   112
	++lib.loaded;
slouken@146
   113
slouken@146
   114
	return 0;
slouken@143
   115
}
slouken@205
   116
void IMG_QuitTIF()
slouken@143
   117
{
slouken@143
   118
	if ( lib.loaded == 0 ) {
slouken@143
   119
		return;
slouken@143
   120
	}
slouken@143
   121
	if ( lib.loaded == 1 ) {
slouken@143
   122
	}
slouken@143
   123
	--lib.loaded;
slouken@143
   124
}
slouken@143
   125
#endif /* LOAD_TIF_DYNAMIC */
slouken@143
   126
slouken@0
   127
/*
slouken@0
   128
 * These are the thunking routine to use the SDL_RWops* routines from
slouken@0
   129
 * libtiff's internals.
slouken@0
   130
*/
slouken@0
   131
slouken@0
   132
static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
   133
{
slouken@0
   134
	return SDL_RWread((SDL_RWops*)fd, buf, 1, size);
slouken@0
   135
}
slouken@0
   136
slouken@0
   137
static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
slouken@0
   138
{
slouken@0
   139
	return SDL_RWseek((SDL_RWops*)fd, offset, origin);
slouken@0
   140
}
slouken@0
   141
slouken@0
   142
static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
   143
{
slouken@0
   144
	return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
slouken@0
   145
}
slouken@0
   146
slouken@0
   147
static int tiff_close(thandle_t fd)
slouken@0
   148
{
slouken@0
   149
	/*
slouken@0
   150
	 * We don't want libtiff closing our SDL_RWops*, but if it's not given
slouken@0
   151
         * a routine to try, and if the image isn't a TIFF, it'll segfault.
slouken@0
   152
	 */
slouken@0
   153
	return 0;
slouken@0
   154
}
slouken@0
   155
slouken@167
   156
static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
slouken@167
   157
{
slouken@167
   158
	return (0);
slouken@167
   159
}
slouken@167
   160
slouken@167
   161
static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
slouken@167
   162
{
slouken@167
   163
	return;
slouken@167
   164
}
slouken@167
   165
slouken@0
   166
static toff_t tiff_size(thandle_t fd)
slouken@0
   167
{
slouken@0
   168
	Uint32 save_pos;
slouken@0
   169
	toff_t size;
slouken@0
   170
slouken@0
   171
	save_pos = SDL_RWtell((SDL_RWops*)fd);
slouken@236
   172
	SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END);
slouken@0
   173
        size = SDL_RWtell((SDL_RWops*)fd);
slouken@236
   174
	SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET);
slouken@0
   175
	return size;
slouken@0
   176
}
slouken@0
   177
slouken@0
   178
int IMG_isTIF(SDL_RWops* src)
slouken@0
   179
{
slouken@117
   180
	int start;
slouken@117
   181
	int is_TIF;
slouken@167
   182
	Uint8 magic[4];
slouken@0
   183
icculus@154
   184
	if ( !src )
icculus@154
   185
		return 0;
slouken@117
   186
	start = SDL_RWtell(src);
slouken@117
   187
	is_TIF = 0;
slouken@167
   188
	if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
slouken@167
   189
		if ( (magic[0] == 'I' &&
slouken@167
   190
                      magic[1] == 'I' &&
slouken@167
   191
		      magic[2] == 0x2a &&
slouken@167
   192
                      magic[3] == 0x00) ||
slouken@167
   193
		     (magic[0] == 'M' &&
slouken@167
   194
                      magic[1] == 'M' &&
slouken@167
   195
		      magic[2] == 0x00 &&
slouken@167
   196
                      magic[3] == 0x2a) ) {
slouken@167
   197
			is_TIF = 1;
slouken@167
   198
		}
slouken@117
   199
	}
slouken@236
   200
	SDL_RWseek(src, start, RW_SEEK_SET);
slouken@117
   201
	return(is_TIF);
slouken@0
   202
}
slouken@0
   203
slouken@0
   204
SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
slouken@0
   205
{
slouken@118
   206
	int start;
slouken@0
   207
	TIFF* tiff;
slouken@0
   208
	SDL_Surface* surface = NULL;
slouken@0
   209
	Uint32 img_width, img_height;
slouken@145
   210
	Uint32 Rmask, Gmask, Bmask, Amask;
slouken@0
   211
	Uint32 x, y;
slouken@0
   212
	Uint32 half;
slouken@0
   213
slouken@98
   214
	if ( !src ) {
slouken@98
   215
		/* The error message has been set in SDL_RWFromFile */
slouken@98
   216
		return NULL;
slouken@98
   217
	}
slouken@118
   218
	start = SDL_RWtell(src);
slouken@0
   219
slouken@233
   220
	if ( !IMG_Init(IMG_INIT_TIF) ) {
slouken@143
   221
		return NULL;
slouken@143
   222
	}
slouken@143
   223
slouken@0
   224
	/* turn off memory mapped access with the m flag */
slouken@143
   225
	tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src, 
slouken@167
   226
		tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
slouken@0
   227
	if(!tiff)
slouken@118
   228
		goto error;
slouken@0
   229
slouken@0
   230
	/* Retrieve the dimensions of the image from the TIFF tags */
slouken@143
   231
	lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
slouken@143
   232
	lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
slouken@0
   233
slouken@4
   234
	Rmask = 0x000000FF;
slouken@4
   235
	Gmask = 0x0000FF00;
slouken@4
   236
	Bmask = 0x00FF0000;
slouken@4
   237
	Amask = 0xFF000000;
slouken@320
   238
	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, img_width, img_height, 32,
slouken@0
   239
		Rmask, Gmask, Bmask, Amask);
slouken@0
   240
	if(!surface)
slouken@118
   241
		goto error;
slouken@0
   242
	
slouken@143
   243
	if(!lib.TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0))
slouken@118
   244
		goto error;
slouken@0
   245
slouken@4
   246
	/* libtiff loads the image upside-down, flip it back */
slouken@0
   247
	half = img_height / 2;
slouken@4
   248
	for(y = 0; y < half; y++)
slouken@0
   249
	{
slouken@4
   250
	        Uint32 *top = (Uint32 *)surface->pixels + y * surface->pitch/4;
slouken@4
   251
	        Uint32 *bot = (Uint32 *)surface->pixels
slouken@4
   252
		              + (img_height - y - 1) * surface->pitch/4;
slouken@0
   253
		for(x = 0; x < img_width; x++)
slouken@0
   254
		{
slouken@4
   255
		        Uint32 tmp = top[x];
slouken@4
   256
			top[x] = bot[x];
slouken@4
   257
			bot[x] = tmp;
slouken@0
   258
		}
slouken@0
   259
	}
slouken@143
   260
	lib.TIFFClose(tiff);
slouken@0
   261
	
slouken@0
   262
	return surface;
slouken@118
   263
slouken@118
   264
error:
slouken@236
   265
	SDL_RWseek(src, start, RW_SEEK_SET);
slouken@118
   266
	if ( surface ) {
slouken@118
   267
		SDL_FreeSurface(surface);
slouken@118
   268
	}
slouken@118
   269
	return NULL;
slouken@0
   270
}
slouken@0
   271
slouken@0
   272
#else
slouken@0
   273
slouken@205
   274
int IMG_InitTIF()
slouken@205
   275
{
slouken@205
   276
	IMG_SetError("TIFF images are not supported");
slouken@205
   277
	return(-1);
slouken@205
   278
}
slouken@205
   279
slouken@205
   280
void IMG_QuitTIF()
slouken@205
   281
{
slouken@205
   282
}
slouken@205
   283
slouken@0
   284
/* See if an image is contained in a data source */
slouken@0
   285
int IMG_isTIF(SDL_RWops *src)
slouken@0
   286
{
slouken@0
   287
	return(0);
slouken@0
   288
}
slouken@0
   289
slouken@0
   290
/* Load a TIFF type image from an SDL datasource */
slouken@0
   291
SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
slouken@0
   292
{
slouken@0
   293
	return(NULL);
slouken@0
   294
}
slouken@0
   295
slouken@0
   296
#endif /* LOAD_TIF */
slouken@237
   297
slouken@237
   298
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */