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