Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions include/SDL3/SDL_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,48 @@ extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface);
*/
extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);

/**
* Load a BMP or PNG image from a seekable SDL data stream.
*
* The new surface should be freed with SDL_DestroySurface(). Not doing so
* will result in a memory leak.
*
* \param src the data stream for the surface.
* \param closeio if true, calls SDL_CloseIO() on `src` before returning, even
* in the case of an error.
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
* SDL_GetError() for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_DestroySurface
* \sa SDL_LoadBMP
* \sa SDL_SaveBMP_IO
*/
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio);

/**
* Load a BMP or PNG image from a file.
*
* The new surface should be freed with SDL_DestroySurface(). Not doing so
* will result in a memory leak.
*
* \param file the BMP file to load.
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
* SDL_GetError() for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_DestroySurface
* \sa SDL_LoadBMP_IO
* \sa SDL_SaveBMP
*/
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface(const char *file);

/**
* Load a BMP image from a seekable SDL data stream.
*
Expand Down
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,8 @@ SDL3_0.0.0 {
SDL_GetPenDeviceType;
SDL_CreateAnimatedCursor;
SDL_RotateSurface;
SDL_LoadSurface_IO;
SDL_LoadSurface;
# extra symbols go here (don't modify this line)
local: *;
};
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1294,3 +1294,5 @@
#define SDL_GetPenDeviceType SDL_GetPenDeviceType_REAL
#define SDL_CreateAnimatedCursor SDL_CreateAnimatedCursor_REAL
#define SDL_RotateSurface SDL_RotateSurface_REAL
#define SDL_LoadSurface_IO SDL_LoadSurface_IO_REAL
#define SDL_LoadSurface SDL_LoadSurface_REAL
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1302,3 +1302,5 @@ SDL_DYNAPI_PROC(int,SDL_GetSystemPageSize,(void),(),return)
SDL_DYNAPI_PROC(SDL_PenDeviceType,SDL_GetPenDeviceType,(SDL_PenID a),(a),return)
SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateAnimatedCursor,(SDL_CursorFrameInfo *a,int b,int c,int d),(a,b,c,d),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_RotateSurface,(SDL_Surface *a,float b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface_IO,(SDL_IOStream *a,bool b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface,(const char *a),(a),return)
30 changes: 24 additions & 6 deletions src/video/SDL_bmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,26 @@ static void CorrectAlphaChannel(SDL_Surface *surface)
}
}

bool SDL_IsBMP(SDL_IOStream* src)
{
Sint64 start;
Uint8 magic[2];
bool is_BMP;

is_BMP = false;
start = SDL_TellIO(src);
if (start >= 0) {
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
if (magic[0] == 'B' && magic[1] == 'M') {
is_BMP = true;
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
}

return is_BMP;
}

SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio)
{
bool was_error = true;
Expand All @@ -195,7 +215,7 @@ SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio)
bool correctAlpha = false;

// The Win32 BMP file header (14 bytes)
char magic[2];
// char magic[2];
// Uint32 bfSize;
// Uint16 bfReserved1;
// Uint16 bfReserved2;
Expand Down Expand Up @@ -227,14 +247,12 @@ SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio)
goto done;
}
SDL_ClearError();
if (SDL_ReadIO(src, magic, 2) != 2) {
goto done;
}
if (SDL_strncmp(magic, "BM", 2) != 0) {
if (!SDL_IsBMP(src)) {
SDL_SetError("File is not a Windows BMP file");
goto done;
}
if (!SDL_ReadU32LE(src, NULL /* bfSize */) ||
if (!SDL_ReadU16LE(src, NULL /* magic (already checked) */) ||
!SDL_ReadU32LE(src, NULL /* bfSize */) ||
!SDL_ReadU16LE(src, NULL /* bfReserved1 */) ||
!SDL_ReadU16LE(src, NULL /* bfReserved2 */) ||
!SDL_ReadU32LE(src, &bfOffBits)) {
Expand Down
36 changes: 22 additions & 14 deletions src/video/SDL_stb.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,31 +328,39 @@ static SDL_Surface *SDL_LoadSTB_IO(SDL_IOStream *src)
}
#endif // SDL_HAVE_STB

SDL_Surface *SDL_LoadPNG_IO(SDL_IOStream *src, bool closeio)
bool SDL_IsPNG(SDL_IOStream* src)
{
Sint64 start;
Uint8 magic[4];
bool is_PNG;

is_PNG = false;
start = SDL_TellIO(src);
if (start >= 0) {
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
if (magic[0] == 0x89 &&
magic[1] == 'P' &&
magic[2] == 'N' &&
magic[3] == 'G') {
is_PNG = true;
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
}

return is_PNG;
}

SDL_Surface *SDL_LoadPNG_IO(SDL_IOStream *src, bool closeio)
{
SDL_Surface *surface = NULL;

CHECK_PARAM(!src) {
SDL_InvalidParamError("src");
goto done;
}

start = SDL_TellIO(src);
is_PNG = false;
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
if (magic[0] == 0x89 &&
magic[1] == 'P' &&
magic[2] == 'N' &&
magic[3] == 'G') {
is_PNG = true;
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);

if (!is_PNG) {
if (!SDL_IsPNG(src)) {
SDL_SetError("File is not a PNG file");
goto done;
}
Expand Down
25 changes: 25 additions & 0 deletions src/video/SDL_surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -3086,3 +3086,28 @@ void SDL_DestroySurface(SDL_Surface *surface)
SDL_free(surface);
}
}

SDL_Surface *SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio)
{
if (SDL_IsBMP(src)) {
return SDL_LoadBMP_IO(src, closeio);
} else if (SDL_IsPNG(src)) {
return SDL_LoadPNG_IO(src, closeio);
} else {
if (closeio) {
SDL_CloseIO(src);
}
SDL_SetError("Unsupported image format");
return NULL;
}
}

SDL_Surface *SDL_LoadSurface(const char *file)
{
SDL_IOStream *stream = SDL_IOFromFile(file, "rb");
if (!stream) {
return NULL;
}

return SDL_LoadSurface_IO(stream, true);
}
2 changes: 2 additions & 0 deletions src/video/SDL_surface_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,7 @@ extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace co
extern float SDL_GetDefaultHDRHeadroom(SDL_Colorspace colorspace);
extern float SDL_GetSurfaceHDRHeadroom(SDL_Surface *surface, SDL_Colorspace colorspace);
extern SDL_Surface *SDL_GetSurfaceImage(SDL_Surface *surface, float display_scale);
extern bool SDL_IsBMP(SDL_IOStream* src);
extern bool SDL_IsPNG(SDL_IOStream* src);

#endif // SDL_surface_c_h_
2 changes: 1 addition & 1 deletion test/testcustomcursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ static const char *cross[] = {

static SDL_Surface *load_image_file(const char *file)
{
SDL_Surface *surface = SDL_strstr(file, ".png") ? SDL_LoadPNG(file) : SDL_LoadBMP(file);
SDL_Surface *surface = SDL_LoadSurface(file);
if (surface) {
if (SDL_GetSurfacePalette(surface)) {
const Uint8 bpp = SDL_BITSPERPIXEL(surface->format);
Expand Down
2 changes: 1 addition & 1 deletion test/testshape.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ int main(int argc, char *argv[])
}

if (image_file) {
shape = SDL_strstr(image_file, ".png") ? SDL_LoadPNG(image_file) : SDL_LoadBMP(image_file);
shape = SDL_LoadSurface(image_file);
if (!shape) {
SDL_Log("Couldn't load %s: %s", image_file, SDL_GetError());
goto quit;
Expand Down
2 changes: 1 addition & 1 deletion test/testutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ SDL_Texture *LoadTexture(SDL_Renderer *renderer, const char *file, bool transpar
file = path;
}

temp = SDL_strstr(file, ".png") ? SDL_LoadPNG(file) : SDL_LoadBMP(file);
temp = SDL_LoadSurface(file);
if (!temp) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
} else {
Expand Down
Loading