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 /* A simple library to load images of various formats as SDL surfaces */
23
24 #include "SDL_image.h"
25
26 #ifdef __EMSCRIPTEN__
27 #include <emscripten/emscripten.h>
28 #endif
29
30 #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
31
32 /* Table of image detection and loading functions */
33 static struct {
34 const char *type;
35 int (SDLCALL *is)(SDL_RWops *src);
36 SDL_Surface *(SDLCALL *load)(SDL_RWops *src);
37 } supported[] = {
38 /* keep magicless formats first */
39 { "TGA", NULL, IMG_LoadTGA_RW },
40 { "CUR", IMG_isCUR, IMG_LoadCUR_RW },
41 { "ICO", IMG_isICO, IMG_LoadICO_RW },
42 { "BMP", IMG_isBMP, IMG_LoadBMP_RW },
43 { "GIF", IMG_isGIF, IMG_LoadGIF_RW },
44 { "JPG", IMG_isJPG, IMG_LoadJPG_RW },
45 { "LBM", IMG_isLBM, IMG_LoadLBM_RW },
46 { "PCX", IMG_isPCX, IMG_LoadPCX_RW },
47 { "PNG", IMG_isPNG, IMG_LoadPNG_RW },
48 { "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */
49 { "SVG", IMG_isSVG, IMG_LoadSVG_RW },
50 { "TIF", IMG_isTIF, IMG_LoadTIF_RW },
51 { "XCF", IMG_isXCF, IMG_LoadXCF_RW },
52 { "XPM", IMG_isXPM, IMG_LoadXPM_RW },
53 { "XV", IMG_isXV, IMG_LoadXV_RW },
54 { "WEBP", IMG_isWEBP, IMG_LoadWEBP_RW },
55 };
56
IMG_Linked_Version(void)57 const SDL_version *IMG_Linked_Version(void)
58 {
59 static SDL_version linked_version;
60 SDL_IMAGE_VERSION(&linked_version);
61 return(&linked_version);
62 }
63
64 extern int IMG_InitJPG(void);
65 extern void IMG_QuitJPG(void);
66 extern int IMG_InitPNG(void);
67 extern void IMG_QuitPNG(void);
68 extern int IMG_InitTIF(void);
69 extern void IMG_QuitTIF(void);
70
71 extern int IMG_InitWEBP(void);
72 extern void IMG_QuitWEBP(void);
73
74 static int initialized = 0;
75
IMG_Init(int flags)76 int IMG_Init(int flags)
77 {
78 int result = 0;
79
80 /* Passing 0 returns the currently initialized loaders */
81 if (!flags) {
82 return initialized;
83 }
84
85 if (flags & IMG_INIT_JPG) {
86 if ((initialized & IMG_INIT_JPG) || IMG_InitJPG() == 0) {
87 result |= IMG_INIT_JPG;
88 }
89 }
90 if (flags & IMG_INIT_PNG) {
91 if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) {
92 result |= IMG_INIT_PNG;
93 }
94 }
95 if (flags & IMG_INIT_TIF) {
96 if ((initialized & IMG_INIT_TIF) || IMG_InitTIF() == 0) {
97 result |= IMG_INIT_TIF;
98 }
99 }
100 if (flags & IMG_INIT_WEBP) {
101 if ((initialized & IMG_INIT_WEBP) || IMG_InitWEBP() == 0) {
102 result |= IMG_INIT_WEBP;
103 }
104 }
105 initialized |= result;
106
107 return result;
108 }
109
IMG_Quit()110 void IMG_Quit()
111 {
112 if (initialized & IMG_INIT_JPG) {
113 IMG_QuitJPG();
114 }
115 if (initialized & IMG_INIT_PNG) {
116 IMG_QuitPNG();
117 }
118 if (initialized & IMG_INIT_TIF) {
119 IMG_QuitTIF();
120 }
121 if (initialized & IMG_INIT_WEBP) {
122 IMG_QuitWEBP();
123 }
124 initialized = 0;
125 }
126
127 #if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
128 /* Load an image from a file */
IMG_Load(const char * file)129 SDL_Surface *IMG_Load(const char *file)
130 {
131 #if __EMSCRIPTEN__
132 int w, h;
133 char *data;
134 SDL_Surface *surf;
135
136 data = emscripten_get_preloaded_image_data(file, &w, &h);
137 if (data != NULL) {
138 surf = SDL_CreateRGBSurface(0, w, h, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
139 if (surf != NULL) {
140 memcpy(surf->pixels, data, w * h * 4);
141 }
142 free(data);
143 return surf;
144 }
145 #endif
146
147 SDL_RWops *src = SDL_RWFromFile(file, "rb");
148 const char *ext = SDL_strrchr(file, '.');
149 if(ext) {
150 ext++;
151 }
152 if(!src) {
153 /* The error message has been set in SDL_RWFromFile */
154 return NULL;
155 }
156 return IMG_LoadTyped_RW(src, 1, ext);
157 }
158 #endif
159
160 /* Load an image from an SDL datasource (for compatibility) */
IMG_Load_RW(SDL_RWops * src,int freesrc)161 SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc)
162 {
163 return IMG_LoadTyped_RW(src, freesrc, NULL);
164 }
165
166 /* Portable case-insensitive string compare function */
IMG_string_equals(const char * str1,const char * str2)167 static int IMG_string_equals(const char *str1, const char *str2)
168 {
169 while ( *str1 && *str2 ) {
170 if ( SDL_toupper((unsigned char)*str1) !=
171 SDL_toupper((unsigned char)*str2) )
172 break;
173 ++str1;
174 ++str2;
175 }
176 return (!*str1 && !*str2);
177 }
178
179 /* Load an image from an SDL datasource, optionally specifying the type */
IMG_LoadTyped_RW(SDL_RWops * src,int freesrc,const char * type)180 SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, const char *type)
181 {
182 int i;
183 SDL_Surface *image;
184
185 /* Make sure there is something to do.. */
186 if ( src == NULL ) {
187 IMG_SetError("Passed a NULL data source");
188 return(NULL);
189 }
190
191 /* See whether or not this data source can handle seeking */
192 if ( SDL_RWseek(src, 0, RW_SEEK_CUR) < 0 ) {
193 IMG_SetError("Can't seek in this data source");
194 if(freesrc)
195 SDL_RWclose(src);
196 return(NULL);
197 }
198
199 #ifdef __EMSCRIPTEN__
200 /*load through preloadedImages*/
201
202 if ( src->type == SDL_RWOPS_STDFILE ) {
203 int w, h, success;
204 char *data;
205 SDL_Surface *surf;
206
207 data = emscripten_get_preloaded_image_data_from_FILE(src->hidden.stdio.fp, &w, &h);
208
209 if(data)
210 {
211 surf = SDL_CreateRGBSurface(0, w, h, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
212 if (surf != NULL) {
213 memcpy(surf->pixels, data, w * h * 4);
214 }
215 free(data);
216
217 if(freesrc)
218 SDL_RWclose(src);
219
220 /* If SDL_CreateRGBSurface returns NULL, it has set the error message for us */
221 return surf;
222 }
223 }
224 #endif
225
226 /* Detect the type of image being loaded */
227 image = NULL;
228 for ( i=0; i < ARRAYSIZE(supported); ++i ) {
229 if(supported[i].is) {
230 if(!supported[i].is(src))
231 continue;
232 } else {
233 /* magicless format */
234 if(!type
235 || !IMG_string_equals(type, supported[i].type))
236 continue;
237 }
238 #ifdef DEBUG_IMGLIB
239 fprintf(stderr, "IMGLIB: Loading image as %s\n",
240 supported[i].type);
241 #endif
242 long long start = aos_now_ms();
243 image = supported[i].load(src);
244 printf("load image duration %d ms\n", (int)(aos_now_ms() - start));
245 if(freesrc)
246 SDL_RWclose(src);
247 return image;
248 }
249
250 if ( freesrc ) {
251 SDL_RWclose(src);
252 }
253 IMG_SetError("Unsupported image format");
254 return NULL;
255 }
256
257 #if SDL_VERSION_ATLEAST(2,0,0)
IMG_LoadTexture(SDL_Renderer * renderer,const char * file)258 SDL_Texture *IMG_LoadTexture(SDL_Renderer *renderer, const char *file)
259 {
260 SDL_Texture *texture = NULL;
261 SDL_Surface *surface = IMG_Load(file);
262 if (surface) {
263 texture = SDL_CreateTextureFromSurface(renderer, surface);
264 SDL_FreeSurface(surface);
265 }
266 return texture;
267 }
268
IMG_LoadTexture_RW(SDL_Renderer * renderer,SDL_RWops * src,int freesrc)269 SDL_Texture *IMG_LoadTexture_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc)
270 {
271 SDL_Texture *texture = NULL;
272 SDL_Surface *surface = IMG_Load_RW(src, freesrc);
273 if (surface) {
274 texture = SDL_CreateTextureFromSurface(renderer, surface);
275 SDL_FreeSurface(surface);
276 }
277 return texture;
278 }
279
IMG_LoadTextureTyped_RW(SDL_Renderer * renderer,SDL_RWops * src,int freesrc,const char * type)280 SDL_Texture *IMG_LoadTextureTyped_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc, const char *type)
281 {
282 SDL_Texture *texture = NULL;
283 SDL_Surface *surface = IMG_LoadTyped_RW(src, freesrc, type);
284 if (surface) {
285 texture = SDL_CreateTextureFromSurface(renderer, surface);
286 SDL_FreeSurface(surface);
287 }
288 return texture;
289 }
290 #endif /* SDL 2.0 */
291