1 /*
2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2019 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_WIC_BACKEND)) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
23
24 /* This is a TIFF image file loading framework */
25
26 #include "SDL_image.h"
27
28 #ifdef LOAD_TIF
29
30 #include <tiffio.h>
31
32 static struct {
33 int loaded;
34 void *handle;
35 TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
36 void (*TIFFClose)(TIFF*);
37 int (*TIFFGetField)(TIFF*, ttag_t, ...);
38 int (*TIFFReadRGBAImageOriented)(TIFF*, uint32, uint32, uint32*, int, int);
39 TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
40 } lib;
41
42 #ifdef LOAD_TIF_DYNAMIC
43 #define FUNCTION_LOADER(FUNC, SIG) \
44 lib.FUNC = (SIG) SDL_LoadFunction(lib.handle, #FUNC); \
45 if (lib.FUNC == NULL) { SDL_UnloadObject(lib.handle); return -1; }
46 #else
47 #define FUNCTION_LOADER(FUNC, SIG) \
48 lib.FUNC = FUNC;
49 #endif
50
IMG_InitTIF()51 int IMG_InitTIF()
52 {
53 if ( lib.loaded == 0 ) {
54 #ifdef LOAD_TIF_DYNAMIC
55 lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
56 if ( lib.handle == NULL ) {
57 return -1;
58 }
59 #endif
60 FUNCTION_LOADER(TIFFClientOpen, TIFF * (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
61 FUNCTION_LOADER(TIFFClose, void (*)(TIFF*))
62 FUNCTION_LOADER(TIFFGetField, int (*)(TIFF*, ttag_t, ...))
63 FUNCTION_LOADER(TIFFReadRGBAImageOriented, int (*)(TIFF*, uint32, uint32, uint32*, int, int))
64 FUNCTION_LOADER(TIFFSetErrorHandler, TIFFErrorHandler (*)(TIFFErrorHandler))
65 }
66 ++lib.loaded;
67
68 return 0;
69 }
IMG_QuitTIF()70 void IMG_QuitTIF()
71 {
72 if ( lib.loaded == 0 ) {
73 return;
74 }
75 if ( lib.loaded == 1 ) {
76 #ifdef LOAD_TIF_DYNAMIC
77 SDL_UnloadObject(lib.handle);
78 #endif
79 }
80 --lib.loaded;
81 }
82
83 /*
84 * These are the thunking routine to use the SDL_RWops* routines from
85 * libtiff's internals.
86 */
87
tiff_read(thandle_t fd,tdata_t buf,tsize_t size)88 static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
89 {
90 return (tsize_t)SDL_RWread((SDL_RWops*)fd, buf, 1, size);
91 }
92
tiff_seek(thandle_t fd,toff_t offset,int origin)93 static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
94 {
95 return SDL_RWseek((SDL_RWops*)fd, offset, origin);
96 }
97
tiff_write(thandle_t fd,tdata_t buf,tsize_t size)98 static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
99 {
100 return (tsize_t)SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
101 }
102
tiff_close(thandle_t fd)103 static int tiff_close(thandle_t fd)
104 {
105 /*
106 * We don't want libtiff closing our SDL_RWops*, but if it's not given
107 * a routine to try, and if the image isn't a TIFF, it'll segfault.
108 */
109 return 0;
110 }
111
tiff_map(thandle_t fd,tdata_t * pbase,toff_t * psize)112 static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
113 {
114 return (0);
115 }
116
tiff_unmap(thandle_t fd,tdata_t base,toff_t size)117 static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
118 {
119 return;
120 }
121
tiff_size(thandle_t fd)122 static toff_t tiff_size(thandle_t fd)
123 {
124 Sint64 save_pos;
125 toff_t size;
126
127 save_pos = SDL_RWtell((SDL_RWops*)fd);
128 SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END);
129 size = SDL_RWtell((SDL_RWops*)fd);
130 SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET);
131 return size;
132 }
133
IMG_isTIF(SDL_RWops * src)134 int IMG_isTIF(SDL_RWops* src)
135 {
136 Sint64 start;
137 int is_TIF;
138 Uint8 magic[4];
139
140 if ( !src )
141 return 0;
142 start = SDL_RWtell(src);
143 is_TIF = 0;
144 if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
145 if ( (magic[0] == 'I' &&
146 magic[1] == 'I' &&
147 magic[2] == 0x2a &&
148 magic[3] == 0x00) ||
149 (magic[0] == 'M' &&
150 magic[1] == 'M' &&
151 magic[2] == 0x00 &&
152 magic[3] == 0x2a) ) {
153 is_TIF = 1;
154 }
155 }
156 SDL_RWseek(src, start, RW_SEEK_SET);
157 return(is_TIF);
158 }
159
IMG_LoadTIF_RW(SDL_RWops * src)160 SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
161 {
162 Sint64 start;
163 TIFF* tiff = NULL;
164 SDL_Surface* surface = NULL;
165 Uint32 img_width, img_height;
166 Uint32 Rmask, Gmask, Bmask, Amask;
167
168 if ( !src ) {
169 /* The error message has been set in SDL_RWFromFile */
170 return NULL;
171 }
172 start = SDL_RWtell(src);
173
174 if ( (IMG_Init(IMG_INIT_TIF) & IMG_INIT_TIF) == 0 ) {
175 return NULL;
176 }
177
178 /* turn off memory mapped access with the m flag */
179 tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src,
180 tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
181 if(!tiff)
182 goto error;
183
184 /* Retrieve the dimensions of the image from the TIFF tags */
185 lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
186 lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
187
188 Rmask = 0x000000FF;
189 Gmask = 0x0000FF00;
190 Bmask = 0x00FF0000;
191 Amask = 0xFF000000;
192 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, img_width, img_height, 32,
193 Rmask, Gmask, Bmask, Amask);
194 if(!surface)
195 goto error;
196
197 if(!lib.TIFFReadRGBAImageOriented(tiff, img_width, img_height, (uint32 *)surface->pixels, ORIENTATION_TOPLEFT, 0))
198 goto error;
199
200 lib.TIFFClose(tiff);
201
202 return surface;
203
204 error:
205 SDL_RWseek(src, start, RW_SEEK_SET);
206 if (surface) {
207 SDL_FreeSurface(surface);
208 }
209 if (tiff) {
210 lib.TIFFClose(tiff);
211 }
212 return NULL;
213 }
214
215 #else
216
IMG_InitTIF()217 int IMG_InitTIF()
218 {
219 IMG_SetError("TIFF images are not supported");
220 return(-1);
221 }
222
IMG_QuitTIF()223 void IMG_QuitTIF()
224 {
225 }
226
227 /* See if an image is contained in a data source */
IMG_isTIF(SDL_RWops * src)228 int IMG_isTIF(SDL_RWops *src)
229 {
230 return(0);
231 }
232
233 /* Load a TIFF type image from an SDL datasource */
IMG_LoadTIF_RW(SDL_RWops * src)234 SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
235 {
236 return(NULL);
237 }
238
239 #endif /* LOAD_TIF */
240
241 #endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
242