forked from sdlpal/sdlpal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SDL_stbimage.h
626 lines (526 loc) · 19.9 KB
/
SDL_stbimage.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
/*
* A small header-only library to load an image into a RGB(A) SDL_Surface*,
* like a stripped down version of SDL_Image, but using stb_image.h to decode
* images and thus without any further external dependencies.
* Supports all filetypes supported by stb_image (JPEG, PNG, TGA, BMP, PSD, ...
* See stb_image.h for details).
*
* (C) 2015 Daniel Gibson
*
* Homepage: https://github.com/DanielGibson/Snippets/
*
* Dependencies:
* libSDL2 http://www.libsdl.org
* stb_image.h https://github.com/nothings/stb
*
* Usage:
* Put this file and stb_image.h somewhere in your project.
* In *one* of your .c/.cpp files, do
* #define SDL_STBIMAGE_IMPLEMENTATION
* #include "SDL_stbimage.h"
* to create the implementation of this library in that file.
* You can just #include "SDL_stbimage.h" (without the #define) in other source
* files to use it there. (See also below this comment for an usage example)
* This header implicitly #includes <SDL.h> and "stb_image.h".
*
* You can #define SDL_STBIMG_DEF before including this header if you want to
* prepend anything to the function signatures (like "static", "inline",
* "__declspec(dllexport)", ...)
* Example: #define SDL_STBIMG_DEF static inline
*
* By default, this deactivates stb_image's load from file functions via
* #define STBI_NO_STDIO, as they use stdio.h and that adds a dependency to the
* CRT on windows and with SDL you're better off using SDL_RWops, incl. SDL_RWFromFile()
* If you wanna use stbi_load(), stbi_info(), stbi_load_from_file() etc anyway, do
* #define SDL_STBIMG_ALLOW_STDIO
* before including this header.
* (Note that all the STBIMG_* functions of this lib will work without it)
*
* stb_image.h uses assert.h by default. You can #define STBI_ASSERT(x)
* before the implementation-#include of SDL_stbimage.h to avoid that.
* By default stb_image supports HDR images, for that it needs pow() from libm.
* If you don't need HDR (it can't be loaded into a SDL_Surface anyway),
* #define STBI_NO_LINEAR and #define STBI_NO_HDR before including this header.
*
* License:
* This software is dual-licensed to the public domain and under the following
* license: you are granted a perpetual, irrevocable license to copy, modify,
* publish, and distribute this file as you see fit.
* No warranty implied; use at your own risk.
*
* So you can do whatever you want with this code, including copying it
* (or parts of it) into your own source.
* No need to mention me or this "license" in your code or docs, even though
* it would be appreciated, of course.
*/
#if 0 // Usage Example:
#define SDL_STBIMAGE_IMPLEMENTATION
#include "SDL_stbimage.h"
void yourFunction(const char* imageFilePath)
{
SDL_Surface* surf = STBIMG_Load(imageFilePath);
if(surf == NULL) {
printf("ERROR: Couldn't load %s, reason: %s\n", imageFilePath, SDL_GetError());
exit(1);
}
// ... do something with surf ...
SDL_FreeSurface(surf);
}
#endif // 0 (usage example)
#ifndef SDL__STBIMAGE_H
#define SDL__STBIMAGE_H
// if you really think you need <SDL2/SDL.h> here instead.. feel free to change it,
// but the cool kids have path/to/include/SDL2/ in their compilers include path.
#include <SDL.h>
#ifndef SDL_STBIMG_ALLOW_STDIO
#define STBI_NO_STDIO // don't need STDIO, will use SDL_RWops to open files
#endif
#include "stb_image.h"
// this allows you to prepend stuff to function signatures, e.g. "static"
#ifndef SDL_STBIMG_DEF
// by default it's empty
#define SDL_STBIMG_DEF
#endif // DG_MISC_DEF
#ifdef __cplusplus
extern "C" {
#endif
// loads the image file at the given path into a RGB(A) SDL_Surface
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load(const char* file);
// loads the image file in the given memory buffer into a RGB(A) SDL_Surface
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_LoadFromMemory(const unsigned char* buffer, int length);
// loads an image file into a RGB(A) SDL_Surface from a seekable SDL_RWops (src)
// if you set freesrc to non-zero, SDL_RWclose(src) will be executed after reading.
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW(SDL_RWops* src, int freesrc);
// Creates an SDL_Surface* using the raw RGB(A) pixelData with given width/height
// (this doesn't use stb_image and is just a simple SDL_CreateSurfaceFrom()-wrapper)
// ! It must be byte-wise 24bit RGB ("888", bytesPerPixel=3) !
// ! or byte-wise 32bit RGBA ("8888", bytesPerPixel=4) data !
// If freeWithSurface is SDL_TRUE, SDL_FreeSurface() will free the pixelData
// you passed with SDL_free() - NOTE that you should only do that if pixelData
// was allocated with SDL_malloc(), SDL_calloc() or SDL_realloc()!
// Returns NULL on error (in that case pixelData won't be freed!),
// use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_CreateSurface(unsigned char* pixelData, int width, int height,
int bytesPerPixel, SDL_bool freeWithSurface);
#if SDL_MAJOR_VERSION > 1
// loads the image file at the given path into a RGB(A) SDL_Texture
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture(SDL_Renderer* renderer, const char* file);
// loads the image file in the given memory buffer into a RGB(A) SDL_Texture
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTextureFromMemory(SDL_Renderer* renderer, const unsigned char* buffer, int length);
// loads an image file into a RGB(A) SDL_Texture from a seekable SDL_RWops (src)
// if you set freesrc to non-zero, SDL_RWclose(src) will be executed after reading.
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_RW(SDL_Renderer* renderer, SDL_RWops* src, int freesrc);
// Creates an SDL_Texture* using the raw RGB(A) pixelData with given width/height
// (this doesn't use stb_image and is just a simple SDL_CreateSurfaceFrom()-wrapper)
// ! It must be byte-wise 24bit RGB ("888", bytesPerPixel=3) !
// ! or byte-wise 32bit RGBA ("8888", bytesPerPixel=4) data !
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Texture*
STBIMG_CreateTexture(SDL_Renderer* renderer, const unsigned char* pixelData,
int width, int height, int bytesPerPixel);
#endif // SDL_MAJOR_VERSION > 1
typedef struct {
SDL_RWops* src;
stbi_io_callbacks stb_cbs;
int atEOF; // defaults to 0; 1: reached EOF or error on read, 2: error on seek
} STBIMG_stbio_RWops;
// creates stbi_io_callbacks and userdata to use stbi_*_from_callbacks() directly,
// especially useful to use SDL_RWops with stb_image, without using SDL_Surface
// src must be readable and seekable!
// Returns SDL_FALSE on error (SDL_GetError() will give you info), else SDL_TRUE
// NOTE: If you want to use src twice (e.g. for info and load), remember to rewind
// it by seeking back to its initial position and resetting out->atEOF to 0
// inbetween the uses!
SDL_STBIMG_DEF SDL_bool STBIMG_stbi_callback_from_RW(SDL_RWops* src, STBIMG_stbio_RWops* out);
#if 0 // Use STBIMG_stbi_callback_from_RW() like this:
SDL_RWops* src = ...; // wherever it's from
STBIMG_stbio_RWops io;
if(!STBIMG_stbi_callback_from_RW(src, &io)) {
printf("ERROR creating stbio callbacks: %s\n", SDL_GetError());
exit(1);
}
Sint64 origSrcPosition = SDL_RWtell(src);
int w, h, fmt;
if(!stbi_info_from_callbacks(&io.stb_cbs, &io, &w, &h, &fmt)) {
printf("stbi_info_from_callbacks() failed, reason: %s\n", stbi_failure_reason());
exit(1);
}
printf("image is %d x %d pixels with %d bytes per pixel\n", w, h, fmt);
// rewind src before using it again in stbi_load_from_callbacks()
if(SDL_RWseek(src, origSrcPosition, RW_SEEK_SET) < 0)
{
printf("ERROR: src not be seekable!\n");
exit(1);
}
io.atEOF = 0; // remember to reset atEOF, too!
unsigned char* data;
data = stbi_load_from_callbacks(&io.stb_cbs, &io, &w, &h, &fmt, 0);
if(data == NULL) {
printf("stbi_load_from_callbacks() failed, reason: %s\n", stbi_failure_reason());
exit(1);
}
// ... do something with data ...
stbi_image_free(data);
#endif // 0 (STBIMG_stbi_callback_from_RW() example)
#if SDL_MAJOR_VERSION > 1
// loads an image file into a RGB(A) SDL_Surface from a SDL_RWops (src)
// - without using SDL_RWseek(), for streams that don't support or are slow
// at seeking. It reads everything into a buffer and calls STBIMG_LoadFromMemory()
// You should probably only use this if you *really* have performance problems
// because of seeking or your src doesn't support SDL_RWseek(), but SDL_RWsize()
// src must at least support SDL_RWread() and SDL_RWsize()
// if you set freesrc to non-zero, SDL_RWclose(src) will be executed after reading.
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW_noSeek(SDL_RWops* src, int freesrc);
// the same for textures (you should probably not use this one, either..)
SDL_STBIMG_DEF SDL_Texture* STBIMG_LoadTexture_RW_noSeek(SDL_Renderer* renderer, SDL_RWops* src, int freesrc);
#endif // SDL_MAJOR_VERSION > 1
#ifdef __cplusplus
} // extern "C"
#endif
#endif // SDL__STBIMAGE_H
// ############# Below: Implementation ###############
#ifdef SDL_STBIMAGE_IMPLEMENTATION
// make stb_image use SDL_malloc etc, so SDL_FreeSurface() can SDL_free()
// the data allocated by stb_image
#define STBI_MALLOC SDL_malloc
#define STBI_REALLOC SDL_realloc
#define STBI_FREE SDL_free
#define STB_IMAGE_IMPLEMENTATION
#ifndef SDL_STBIMG_ALLOW_STDIO
#define STBI_NO_STDIO // don't need STDIO, will use SDL_RWops to open files
#endif
#include "stb_image.h"
typedef struct {
unsigned char* data;
int w;
int h;
int format; // 3: RGB, 4: RGBA
} STBIMG__image;
static SDL_Surface* STBIMG__CreateSurfaceImpl(STBIMG__image img, int freeWithSurface)
{
SDL_Surface* surf = NULL;
Uint32 rmask, gmask, bmask, amask;
// ok, the following is pretty stupid.. SDL_CreateRGBSurfaceFrom() pretends to use
// a void* for the data, but it's really treated as endian-specific Uint32*
// and there isn't even an SDL_PIXELFORMAT_* for 32bit byte-wise RGBA
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int shift = (img.format == STBI_rgb) ? 8 : 0;
rmask = 0xff000000 >> shift;
gmask = 0x00ff0000 >> shift;
bmask = 0x0000ff00 >> shift;
amask = 0x000000ff >> shift;
#else // little endian, like x86
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = (img.format == STBI_rgb) ? 0 : 0xff000000;
#endif
surf = SDL_CreateRGBSurfaceFrom((void*)img.data, img.w, img.h,
img.format*8, img.format*img.w,
rmask, gmask, bmask, amask);
if(surf == NULL)
{
// hopefully SDL_CreateRGBSurfaceFrom() has set an sdl error
return NULL;
}
if(freeWithSurface)
{
// SDL_Surface::flags is documented to be read-only.. but if the pixeldata
// has been allocated with SDL_malloc()/SDL_calloc()/SDL_realloc() this
// should work (and it currently does) + @icculus said it's reasonably safe:
// https://twitter.com/icculus/status/667036586610139137 :-)
// clear the SDL_PREALLOC flag, so SDL_FreeSurface() free()s the data passed from img.data
surf->flags &= ~SDL_PREALLOC;
}
return surf;
}
SDL_STBIMG_DEF SDL_Surface* STBIMG_LoadFromMemory(const unsigned char* buffer, int length)
{
STBIMG__image img = {0};
int bppToUse = 0;
int inforet = 0;
SDL_Surface* ret = NULL;
if(buffer == NULL)
{
SDL_SetError("STBIMG_LoadFromMemory(): passed buffer was NULL!");
return NULL;
}
if(length <= 0)
{
SDL_SetError("STBIMG_LoadFromMemory(): passed invalid length: %d!", length);
return NULL;
}
inforet = stbi_info_from_memory(buffer, length, &img.w, &img.h, &img.format);
if(!inforet)
{
SDL_SetError("STBIMG_LoadFromMemory(): Couldn't get image info: %s!\n", stbi_failure_reason());
return NULL;
}
// no alpha => use RGB, else use RGBA
bppToUse = (img.format == STBI_grey || img.format == STBI_rgb) ? STBI_rgb : STBI_rgb_alpha;
img.data = stbi_load_from_memory(buffer, length, &img.w, &img.h, &img.format, bppToUse);
if(img.data == NULL)
{
SDL_SetError("STBIMG_LoadFromMemory(): Couldn't load image: %s!\n", stbi_failure_reason());
return NULL;
}
img.format = bppToUse;
ret = STBIMG__CreateSurfaceImpl(img, 1);
if(ret == NULL)
{
// no need to log an error here, it was an SDL error which should still be available through SDL_GetError()
SDL_free(img.data);
return NULL;
}
return ret;
}
// fill 'data' with 'size' bytes. return number of bytes actually read
static int STBIMG__io_read(void* user, char* data, int size)
{
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
int ret = SDL_RWread(io->src, data, sizeof(char), size);
if(ret == 0)
{
// we're at EOF or some error happend
io->atEOF = 1;
}
return (int)ret*sizeof(char);
}
// skip the next 'n' bytes, or 'unget' the last -n bytes if negative
static void STBIMG__io_skip(void* user, int n)
{
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
if(SDL_RWseek(io->src, n, RW_SEEK_CUR) == -1)
{
// an error happened during seeking, hopefully setting EOF will make stb_image abort
io->atEOF = 2; // set this to 2 for "aborting because seeking failed" (stb_image only cares about != 0)
}
}
// returns nonzero if we are at end of file/data
static int STBIMG__io_eof(void* user)
{
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
return io->atEOF;
}
SDL_STBIMG_DEF SDL_bool STBIMG_stbi_callback_from_RW(SDL_RWops* src, STBIMG_stbio_RWops* out)
{
if(out == NULL)
{
SDL_SetError("STBIMG_stbi_callback_from_RW(): out must not be NULL!");
return SDL_FALSE;
}
// make sure out is at least initialized to something deterministic
memset(out, 0, sizeof(*out));
if(src == NULL)
{
SDL_SetError("STBIMG_stbi_callback_from_RW(): src must not be NULL!");
return SDL_FALSE;
}
out->src = src;
out->atEOF = 0;
out->stb_cbs.read = STBIMG__io_read;
out->stb_cbs.skip = STBIMG__io_skip;
out->stb_cbs.eof = STBIMG__io_eof;
return SDL_TRUE;
}
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW(SDL_RWops* src, int freesrc)
{
STBIMG__image img = {0};
int bppToUse = 0;
int inforet = 0;
SDL_Surface* ret = NULL;
Sint64 srcOffset = 0;
STBIMG_stbio_RWops cbData;
if(src == NULL)
{
SDL_SetError("STBIMG_Load_RW(): src was NULL!");
return NULL;
}
srcOffset = SDL_RWtell(src);
if(srcOffset < 0)
{
SDL_SetError("STBIMG_Load_RW(): src must be seekable, maybe use STBIMG_Load_RW_noSeek() instead!");
// TODO: or do that automatically? but I think the user should be aware of what they're doing
goto end;
}
if(!STBIMG_stbi_callback_from_RW(src, &cbData))
{
goto end;
}
inforet = stbi_info_from_callbacks(&cbData.stb_cbs, &cbData, &img.w, &img.h, &img.format);
if(!inforet)
{
if(cbData.atEOF == 2) SDL_SetError("STBIMG_Load_RW(): src must be seekable!");
else SDL_SetError("STBIMG_Load_RW(): Couldn't get image info: %s!\n", stbi_failure_reason());
goto end;
}
// rewind src so stbi_load_from_callbacks() will start reading from the beginning again
if(SDL_RWseek(src, srcOffset, RW_SEEK_SET) < 0)
{
SDL_SetError("STBIMG_Load_RW(): src must be seekable!");
goto end;
}
cbData.atEOF = 0; // we've rewinded (rewound?)
// no alpha => use RGB, else use RGBA
bppToUse = (img.format == STBI_grey || img.format == STBI_rgb) ? STBI_rgb : STBI_rgb_alpha;
img.data = stbi_load_from_callbacks(&cbData.stb_cbs, &cbData, &img.w, &img.h, &img.format, bppToUse);
if(img.data == NULL)
{
SDL_SetError("STBIMG_Load_RW(): Couldn't load image: %s!\n", stbi_failure_reason());
goto end;
}
img.format = bppToUse;
ret = STBIMG__CreateSurfaceImpl(img, 1);
if(ret == NULL)
{
// no need to log an error here, it was an SDL error which should still be available through SDL_GetError()
SDL_free(img.data);
img.data = NULL;
goto end;
}
end:
if(freesrc)
{
SDL_RWclose(src);
}
else if(img.data == NULL)
{
// if data is still NULL, there was an error and we should probably
// seek src back to where it was when this function was called
SDL_RWseek(src, srcOffset, RW_SEEK_SET);
}
return ret;
}
#if SDL_MAJOR_VERSION > 1
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW_noSeek(SDL_RWops* src, int freesrc)
{
unsigned char* buf = NULL;
Sint64 fileSize = 0;
SDL_Surface* ret = NULL;
if(src == NULL)
{
SDL_SetError("STBIMG_Load_RW_noSeek(): src was NULL!");
return NULL;
}
fileSize = SDL_RWsize(src);
if(fileSize < 0)
{
goto end; // SDL should have set an error already
}
else if(fileSize == 0)
{
SDL_SetError("STBIMG_Load_RW_noSeek(): SDL_RWsize(src) returned 0 => empty file/stream?!");
goto end;
}
else if(fileSize > 0x7FFFFFFF)
{
// stb_image.h uses ints for all sizes, so we can't support more
// (but >2GB images are insane anyway)
SDL_SetError("STBIMG_Load_RW_noSeek(): SDL_RWsize(src) too big (> 2GB)!");
goto end;
}
buf = (unsigned char*)SDL_malloc(fileSize);
if(buf == NULL)
{
SDL_SetError("STBIMG_Load_RW_noSeek(): Couldn't allocate buffer to read src into!");
goto end;
}
if(SDL_RWread(src, buf, fileSize, 1) > 0)
{
// if that fails, STBIMG_LoadFromMemory() has set an SDL error
// and ret is NULL, so nothing special to do for us
ret = STBIMG_LoadFromMemory(buf, fileSize);
}
end:
if(freesrc)
{
SDL_RWclose(src);
}
SDL_free(buf);
return ret;
}
#endif // SDL_MAJOR_VERSION > 1
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load(const char* file)
{
SDL_RWops* src = SDL_RWFromFile(file, "rb");
if(src == NULL) return NULL;
return STBIMG_Load_RW(src, 1);
}
SDL_STBIMG_DEF SDL_Surface* STBIMG_CreateSurface(unsigned char* pixelData, int width, int height, int bytesPerPixel, SDL_bool freeWithSurface)
{
STBIMG__image img;
if(pixelData == NULL)
{
SDL_SetError("STBIMG_CreateSurface(): passed pixelData was NULL!");
return NULL;
}
if(bytesPerPixel != 3 && bytesPerPixel != 4)
{
SDL_SetError("STBIMG_CreateSurface(): passed bytesPerPixel = %d, only 3 (24bit RGB) and 4 (32bit RGBA) are allowed!", bytesPerPixel);
return NULL;
}
if(width <= 0 || height <= 0)
{
SDL_SetError("STBIMG_CreateSurface(): width and height must be > 0!");
return NULL;
}
img.data = pixelData;
img.w = width;
img.h = height;
img.format = bytesPerPixel;
return STBIMG__CreateSurfaceImpl(img, freeWithSurface);
}
#if SDL_MAJOR_VERSION > 1
static SDL_Texture* STBIMG__SurfToTex(SDL_Renderer* renderer, SDL_Surface* surf)
{
SDL_Texture* ret = NULL;
if(surf != NULL)
{
ret = SDL_CreateTextureFromSurface(renderer, surf);
SDL_FreeSurface(surf); // not needed anymore, it's copied into tex
}
// if surf is NULL, whatever tried to create it should have called SDL_SetError(),
// if SDL_CreateTextureFromSurface() returned NULL it should have set an error
// so whenever this returns NULL, the user should be able to get a useful
// error-message with SDL_GetError().
return ret;
}
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture(SDL_Renderer* renderer, const char* file)
{
return STBIMG__SurfToTex(renderer, STBIMG_Load(file));
}
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTextureFromMemory(SDL_Renderer *renderer, const unsigned char* buffer, int length)
{
return STBIMG__SurfToTex(renderer, STBIMG_LoadFromMemory(buffer, length));
}
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_RW(SDL_Renderer* renderer, SDL_RWops* src, int freesrc)
{
return STBIMG__SurfToTex(renderer, STBIMG_Load_RW(src, freesrc));
}
SDL_STBIMG_DEF SDL_Texture*
STBIMG_CreateTexture(SDL_Renderer* renderer, const unsigned char* pixelData,
int width, int height, int bytesPerPixel)
{
SDL_Surface* surf = STBIMG_CreateSurface((unsigned char*)pixelData, width, height, bytesPerPixel, SDL_FALSE);
return STBIMG__SurfToTex(renderer, surf);
}
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_RW_noSeek(SDL_Renderer* renderer, SDL_RWops* src, int freesrc)
{
return STBIMG__SurfToTex(renderer, STBIMG_Load_RW_noSeek(src, freesrc));
}
#endif // SDL_MAJOR_VERSION > 1
#endif // SDL_STBIMAGE_IMPLEMENTATION