Skip to content

Commit e441283

Browse files
committed
Add SDL_LoadSurface and SDL_LoadSurface_IO
1 parent 5247399 commit e441283

File tree

11 files changed

+124
-23
lines changed

11 files changed

+124
-23
lines changed

include/SDL3/SDL_surface.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,48 @@ extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface);
502502
*/
503503
extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
504504

505+
/**
506+
* Load a BMP or PNG image from a seekable SDL data stream.
507+
*
508+
* The new surface should be freed with SDL_DestroySurface(). Not doing so
509+
* will result in a memory leak.
510+
*
511+
* \param src the data stream for the surface.
512+
* \param closeio if true, calls SDL_CloseIO() on `src` before returning, even
513+
* in the case of an error.
514+
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
515+
* SDL_GetError() for more information.
516+
*
517+
* \threadsafety It is safe to call this function from any thread.
518+
*
519+
* \since This function is available since SDL 3.4.0.
520+
*
521+
* \sa SDL_DestroySurface
522+
* \sa SDL_LoadBMP
523+
* \sa SDL_SaveBMP_IO
524+
*/
525+
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio);
526+
527+
/**
528+
* Load a BMP or PNG image from a file.
529+
*
530+
* The new surface should be freed with SDL_DestroySurface(). Not doing so
531+
* will result in a memory leak.
532+
*
533+
* \param file the BMP file to load.
534+
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
535+
* SDL_GetError() for more information.
536+
*
537+
* \threadsafety It is safe to call this function from any thread.
538+
*
539+
* \since This function is available since SDL 3.4.0.
540+
*
541+
* \sa SDL_DestroySurface
542+
* \sa SDL_LoadBMP_IO
543+
* \sa SDL_SaveBMP
544+
*/
545+
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface(const char *file);
546+
505547
/**
506548
* Load a BMP image from a seekable SDL data stream.
507549
*

src/dynapi/SDL_dynapi.sym

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,8 @@ SDL3_0.0.0 {
12681268
SDL_GetPenDeviceType;
12691269
SDL_CreateAnimatedCursor;
12701270
SDL_RotateSurface;
1271+
SDL_LoadSurface_IO;
1272+
SDL_LoadSurface;
12711273
# extra symbols go here (don't modify this line)
12721274
local: *;
12731275
};

src/dynapi/SDL_dynapi_overrides.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,3 +1294,5 @@
12941294
#define SDL_GetPenDeviceType SDL_GetPenDeviceType_REAL
12951295
#define SDL_CreateAnimatedCursor SDL_CreateAnimatedCursor_REAL
12961296
#define SDL_RotateSurface SDL_RotateSurface_REAL
1297+
#define SDL_LoadSurface_IO SDL_LoadSurface_IO_REAL
1298+
#define SDL_LoadSurface SDL_LoadSurface_REAL

src/dynapi/SDL_dynapi_procs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,3 +1302,5 @@ SDL_DYNAPI_PROC(int,SDL_GetSystemPageSize,(void),(),return)
13021302
SDL_DYNAPI_PROC(SDL_PenDeviceType,SDL_GetPenDeviceType,(SDL_PenID a),(a),return)
13031303
SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateAnimatedCursor,(SDL_CursorFrameInfo *a,int b,int c,int d),(a,b,c,d),return)
13041304
SDL_DYNAPI_PROC(SDL_Surface*,SDL_RotateSurface,(SDL_Surface *a,float b),(a,b),return)
1305+
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface_IO,(SDL_IOStream *a,bool b),(a,b),return)
1306+
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface,(const char *a),(a),return)

src/video/SDL_bmp.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,26 @@ static void CorrectAlphaChannel(SDL_Surface *surface)
177177
}
178178
}
179179

180+
bool SDL_IsBMP(SDL_IOStream* src)
181+
{
182+
Sint64 start;
183+
Uint8 magic[2];
184+
bool is_BMP;
185+
186+
is_BMP = false;
187+
start = SDL_TellIO(src);
188+
if (start >= 0) {
189+
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
190+
if (magic[0] == 'B' && magic[1] == 'M') {
191+
is_BMP = true;
192+
}
193+
}
194+
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
195+
}
196+
197+
return is_BMP;
198+
}
199+
180200
SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio)
181201
{
182202
bool was_error = true;
@@ -195,7 +215,7 @@ SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio)
195215
bool correctAlpha = false;
196216

197217
// The Win32 BMP file header (14 bytes)
198-
char magic[2];
218+
// char magic[2];
199219
// Uint32 bfSize;
200220
// Uint16 bfReserved1;
201221
// Uint16 bfReserved2;
@@ -227,14 +247,12 @@ SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio)
227247
goto done;
228248
}
229249
SDL_ClearError();
230-
if (SDL_ReadIO(src, magic, 2) != 2) {
231-
goto done;
232-
}
233-
if (SDL_strncmp(magic, "BM", 2) != 0) {
250+
if (!SDL_IsBMP(src)) {
234251
SDL_SetError("File is not a Windows BMP file");
235252
goto done;
236253
}
237-
if (!SDL_ReadU32LE(src, NULL /* bfSize */) ||
254+
if (!SDL_ReadU16LE(src, NULL /* magic (already checked) */) ||
255+
!SDL_ReadU32LE(src, NULL /* bfSize */) ||
238256
!SDL_ReadU16LE(src, NULL /* bfReserved1 */) ||
239257
!SDL_ReadU16LE(src, NULL /* bfReserved2 */) ||
240258
!SDL_ReadU32LE(src, &bfOffBits)) {

src/video/SDL_stb.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -328,31 +328,39 @@ static SDL_Surface *SDL_LoadSTB_IO(SDL_IOStream *src)
328328
}
329329
#endif // SDL_HAVE_STB
330330

331-
SDL_Surface *SDL_LoadPNG_IO(SDL_IOStream *src, bool closeio)
331+
bool SDL_IsPNG(SDL_IOStream* src)
332332
{
333333
Sint64 start;
334334
Uint8 magic[4];
335335
bool is_PNG;
336+
337+
is_PNG = false;
338+
start = SDL_TellIO(src);
339+
if (start >= 0) {
340+
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
341+
if (magic[0] == 0x89 &&
342+
magic[1] == 'P' &&
343+
magic[2] == 'N' &&
344+
magic[3] == 'G') {
345+
is_PNG = true;
346+
}
347+
}
348+
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
349+
}
350+
351+
return is_PNG;
352+
}
353+
354+
SDL_Surface *SDL_LoadPNG_IO(SDL_IOStream *src, bool closeio)
355+
{
336356
SDL_Surface *surface = NULL;
337357

338358
CHECK_PARAM(!src) {
339359
SDL_InvalidParamError("src");
340360
goto done;
341361
}
342362

343-
start = SDL_TellIO(src);
344-
is_PNG = false;
345-
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
346-
if (magic[0] == 0x89 &&
347-
magic[1] == 'P' &&
348-
magic[2] == 'N' &&
349-
magic[3] == 'G') {
350-
is_PNG = true;
351-
}
352-
}
353-
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
354-
355-
if (!is_PNG) {
363+
if (!SDL_IsPNG(src)) {
356364
SDL_SetError("File is not a PNG file");
357365
goto done;
358366
}

src/video/SDL_surface.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,3 +3086,28 @@ void SDL_DestroySurface(SDL_Surface *surface)
30863086
SDL_free(surface);
30873087
}
30883088
}
3089+
3090+
SDL_Surface *SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio)
3091+
{
3092+
if (SDL_IsBMP(src)) {
3093+
return SDL_LoadBMP_IO(src, closeio);
3094+
} else if (SDL_IsPNG(src)) {
3095+
return SDL_LoadPNG_IO(src, closeio);
3096+
} else {
3097+
if (closeio) {
3098+
SDL_CloseIO(src);
3099+
}
3100+
SDL_SetError("Unsupported image format");
3101+
return NULL;
3102+
}
3103+
}
3104+
3105+
SDL_Surface *SDL_LoadSurface(const char *file)
3106+
{
3107+
SDL_IOStream *stream = SDL_IOFromFile(file, "rb");
3108+
if (!stream) {
3109+
return NULL;
3110+
}
3111+
3112+
return SDL_LoadSurface_IO(stream, true);
3113+
}

src/video/SDL_surface_c.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,7 @@ extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace co
8989
extern float SDL_GetDefaultHDRHeadroom(SDL_Colorspace colorspace);
9090
extern float SDL_GetSurfaceHDRHeadroom(SDL_Surface *surface, SDL_Colorspace colorspace);
9191
extern SDL_Surface *SDL_GetSurfaceImage(SDL_Surface *surface, float display_scale);
92+
extern bool SDL_IsBMP(SDL_IOStream* src);
93+
extern bool SDL_IsPNG(SDL_IOStream* src);
9294

9395
#endif // SDL_surface_c_h_

test/testcustomcursor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static const char *cross[] = {
111111

112112
static SDL_Surface *load_image_file(const char *file)
113113
{
114-
SDL_Surface *surface = SDL_strstr(file, ".png") ? SDL_LoadPNG(file) : SDL_LoadBMP(file);
114+
SDL_Surface *surface = SDL_LoadSurface(file);
115115
if (surface) {
116116
if (SDL_GetSurfacePalette(surface)) {
117117
const Uint8 bpp = SDL_BITSPERPIXEL(surface->format);

test/testshape.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ int main(int argc, char *argv[])
5454
}
5555

5656
if (image_file) {
57-
shape = SDL_strstr(image_file, ".png") ? SDL_LoadPNG(image_file) : SDL_LoadBMP(image_file);
57+
shape = SDL_LoadSurface(image_file);
5858
if (!shape) {
5959
SDL_Log("Couldn't load %s: %s", image_file, SDL_GetError());
6060
goto quit;

0 commit comments

Comments
 (0)