2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 /* This is a TIFF image file loading framework */
27 #include "SDL_image.h"
36 TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
37 void (*TIFFClose)(TIFF*);
38 int (*TIFFGetField)(TIFF*, ttag_t, ...);
39 int (*TIFFReadRGBAImage)(TIFF*, uint32, uint32, uint32*, int);
40 TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
43 #ifdef LOAD_TIF_DYNAMIC
46 if ( lib.loaded == 0 ) {
47 lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
48 if ( lib.handle == NULL ) {
52 (TIFF* (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
53 SDL_LoadFunction(lib.handle, "TIFFClientOpen");
54 if ( lib.TIFFClientOpen == NULL ) {
55 SDL_UnloadObject(lib.handle);
60 SDL_LoadFunction(lib.handle, "TIFFClose");
61 if ( lib.TIFFClose == NULL ) {
62 SDL_UnloadObject(lib.handle);
66 (int (*)(TIFF*, ttag_t, ...))
67 SDL_LoadFunction(lib.handle, "TIFFGetField");
68 if ( lib.TIFFGetField == NULL ) {
69 SDL_UnloadObject(lib.handle);
72 lib.TIFFReadRGBAImage =
73 (int (*)(TIFF*, uint32, uint32, uint32*, int))
74 SDL_LoadFunction(lib.handle, "TIFFReadRGBAImage");
75 if ( lib.TIFFReadRGBAImage == NULL ) {
76 SDL_UnloadObject(lib.handle);
79 lib.TIFFSetErrorHandler =
80 (TIFFErrorHandler (*)(TIFFErrorHandler))
81 SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler");
82 if ( lib.TIFFSetErrorHandler == NULL ) {
83 SDL_UnloadObject(lib.handle);
93 if ( lib.loaded == 0 ) {
96 if ( lib.loaded == 1 ) {
97 SDL_UnloadObject(lib.handle);
104 if ( lib.loaded == 0 ) {
105 lib.TIFFClientOpen = TIFFClientOpen;
106 lib.TIFFClose = TIFFClose;
107 lib.TIFFGetField = TIFFGetField;
108 lib.TIFFReadRGBAImage = TIFFReadRGBAImage;
109 lib.TIFFSetErrorHandler = TIFFSetErrorHandler;
117 if ( lib.loaded == 0 ) {
120 if ( lib.loaded == 1 ) {
124 #endif /* LOAD_TIF_DYNAMIC */
127 * These are the thunking routine to use the SDL_RWops* routines from
128 * libtiff's internals.
131 static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
133 return SDL_RWread((SDL_RWops*)fd, buf, 1, size);
136 static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
138 return SDL_RWseek((SDL_RWops*)fd, offset, origin);
141 static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
143 return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
146 static int tiff_close(thandle_t fd)
149 * We don't want libtiff closing our SDL_RWops*, but if it's not given
150 * a routine to try, and if the image isn't a TIFF, it'll segfault.
155 static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
160 static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
165 static toff_t tiff_size(thandle_t fd)
170 save_pos = SDL_RWtell((SDL_RWops*)fd);
171 SDL_RWseek((SDL_RWops*)fd, 0, SEEK_END);
172 size = SDL_RWtell((SDL_RWops*)fd);
173 SDL_RWseek((SDL_RWops*)fd, save_pos, SEEK_SET);
177 int IMG_isTIF(SDL_RWops* src)
185 start = SDL_RWtell(src);
187 if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
188 if ( (magic[0] == 'I' &&
195 magic[3] == 0x2a) ) {
199 SDL_RWseek(src, start, SEEK_SET);
203 SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
207 SDL_Surface* surface = NULL;
208 Uint32 img_width, img_height;
209 Uint32 Rmask, Gmask, Bmask, Amask;
214 /* The error message has been set in SDL_RWFromFile */
217 start = SDL_RWtell(src);
219 if ( IMG_Init(IMG_INIT_TIF) < 0 ) {
223 /* turn off memory mapped access with the m flag */
224 tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src,
225 tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
229 /* Retrieve the dimensions of the image from the TIFF tags */
230 lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
231 lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
237 surface = SDL_AllocSurface(SDL_SWSURFACE, img_width, img_height, 32,
238 Rmask, Gmask, Bmask, Amask);
242 if(!lib.TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0))
245 /* libtiff loads the image upside-down, flip it back */
246 half = img_height / 2;
247 for(y = 0; y < half; y++)
249 Uint32 *top = (Uint32 *)surface->pixels + y * surface->pitch/4;
250 Uint32 *bot = (Uint32 *)surface->pixels
251 + (img_height - y - 1) * surface->pitch/4;
252 for(x = 0; x < img_width; x++)
264 SDL_RWseek(src, start, SEEK_SET);
266 SDL_FreeSurface(surface);
275 IMG_SetError("TIFF images are not supported");
283 /* See if an image is contained in a data source */
284 int IMG_isTIF(SDL_RWops *src)
289 /* Load a TIFF type image from an SDL datasource */
290 SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
295 #endif /* LOAD_TIF */