]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libsdl-image/contrib/IMG_tif.c
a9f5511b09ff62c71d4257c782fcaa0f92b77371
[l4.git] / l4 / pkg / libsdl-image / contrib / IMG_tif.c
1 /*
2     SDL_image:  An example image loading library for use with SDL
3     Copyright (C) 1997-2009 Sam Lantinga
4
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.
9
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.
14
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
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22
23 /* This is a TIFF image file loading framework */
24
25 #include <stdio.h>
26
27 #include "SDL_image.h"
28
29 #ifdef LOAD_TIF
30
31 #include <tiffio.h>
32
33 static struct {
34         int loaded;
35         void *handle;
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);
41 } lib;
42
43 #ifdef LOAD_TIF_DYNAMIC
44 int IMG_InitTIF()
45 {
46         if ( lib.loaded == 0 ) {
47                 lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
48                 if ( lib.handle == NULL ) {
49                         return -1;
50                 }
51                 lib.TIFFClientOpen =
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);
56                         return -1;
57                 }
58                 lib.TIFFClose =
59                         (void (*)(TIFF*))
60                         SDL_LoadFunction(lib.handle, "TIFFClose");
61                 if ( lib.TIFFClose == NULL ) {
62                         SDL_UnloadObject(lib.handle);
63                         return -1;
64                 }
65                 lib.TIFFGetField =
66                         (int (*)(TIFF*, ttag_t, ...))
67                         SDL_LoadFunction(lib.handle, "TIFFGetField");
68                 if ( lib.TIFFGetField == NULL ) {
69                         SDL_UnloadObject(lib.handle);
70                         return -1;
71                 }
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);
77                         return -1;
78                 }
79                 lib.TIFFSetErrorHandler =
80                         (TIFFErrorHandler (*)(TIFFErrorHandler))
81                         SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler");
82                 if ( lib.TIFFSetErrorHandler == NULL ) {
83                         SDL_UnloadObject(lib.handle);
84                         return -1;
85                 }
86         }
87         ++lib.loaded;
88
89         return 0;
90 }
91 void IMG_QuitTIF()
92 {
93         if ( lib.loaded == 0 ) {
94                 return;
95         }
96         if ( lib.loaded == 1 ) {
97                 SDL_UnloadObject(lib.handle);
98         }
99         --lib.loaded;
100 }
101 #else
102 int IMG_InitTIF()
103 {
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;
110         }
111         ++lib.loaded;
112
113         return 0;
114 }
115 void IMG_QuitTIF()
116 {
117         if ( lib.loaded == 0 ) {
118                 return;
119         }
120         if ( lib.loaded == 1 ) {
121         }
122         --lib.loaded;
123 }
124 #endif /* LOAD_TIF_DYNAMIC */
125
126 /*
127  * These are the thunking routine to use the SDL_RWops* routines from
128  * libtiff's internals.
129 */
130
131 static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
132 {
133         return SDL_RWread((SDL_RWops*)fd, buf, 1, size);
134 }
135
136 static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
137 {
138         return SDL_RWseek((SDL_RWops*)fd, offset, origin);
139 }
140
141 static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
142 {
143         return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
144 }
145
146 static int tiff_close(thandle_t fd)
147 {
148         /*
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.
151          */
152         return 0;
153 }
154
155 static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
156 {
157         return (0);
158 }
159
160 static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
161 {
162         return;
163 }
164
165 static toff_t tiff_size(thandle_t fd)
166 {
167         Uint32 save_pos;
168         toff_t size;
169
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);
174         return size;
175 }
176
177 int IMG_isTIF(SDL_RWops* src)
178 {
179         int start;
180         int is_TIF;
181         Uint8 magic[4];
182
183         if ( !src )
184                 return 0;
185         start = SDL_RWtell(src);
186         is_TIF = 0;
187         if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
188                 if ( (magic[0] == 'I' &&
189                       magic[1] == 'I' &&
190                       magic[2] == 0x2a &&
191                       magic[3] == 0x00) ||
192                      (magic[0] == 'M' &&
193                       magic[1] == 'M' &&
194                       magic[2] == 0x00 &&
195                       magic[3] == 0x2a) ) {
196                         is_TIF = 1;
197                 }
198         }
199         SDL_RWseek(src, start, SEEK_SET);
200         return(is_TIF);
201 }
202
203 SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
204 {
205         int start;
206         TIFF* tiff;
207         SDL_Surface* surface = NULL;
208         Uint32 img_width, img_height;
209         Uint32 Rmask, Gmask, Bmask, Amask;
210         Uint32 x, y;
211         Uint32 half;
212
213         if ( !src ) {
214                 /* The error message has been set in SDL_RWFromFile */
215                 return NULL;
216         }
217         start = SDL_RWtell(src);
218
219         if ( IMG_Init(IMG_INIT_TIF) < 0 ) {
220                 return NULL;
221         }
222
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);
226         if(!tiff)
227                 goto error;
228
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);
232
233         Rmask = 0x000000FF;
234         Gmask = 0x0000FF00;
235         Bmask = 0x00FF0000;
236         Amask = 0xFF000000;
237         surface = SDL_AllocSurface(SDL_SWSURFACE, img_width, img_height, 32,
238                 Rmask, Gmask, Bmask, Amask);
239         if(!surface)
240                 goto error;
241         
242         if(!lib.TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0))
243                 goto error;
244
245         /* libtiff loads the image upside-down, flip it back */
246         half = img_height / 2;
247         for(y = 0; y < half; y++)
248         {
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++)
253                 {
254                         Uint32 tmp = top[x];
255                         top[x] = bot[x];
256                         bot[x] = tmp;
257                 }
258         }
259         lib.TIFFClose(tiff);
260         
261         return surface;
262
263 error:
264         SDL_RWseek(src, start, SEEK_SET);
265         if ( surface ) {
266                 SDL_FreeSurface(surface);
267         }
268         return NULL;
269 }
270
271 #else
272
273 int IMG_InitTIF()
274 {
275         IMG_SetError("TIFF images are not supported");
276         return(-1);
277 }
278
279 void IMG_QuitTIF()
280 {
281 }
282
283 /* See if an image is contained in a data source */
284 int IMG_isTIF(SDL_RWops *src)
285 {
286         return(0);
287 }
288
289 /* Load a TIFF type image from an SDL datasource */
290 SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
291 {
292         return(NULL);
293 }
294
295 #endif /* LOAD_TIF */