Support loading JPEG images through SDL_LoadSurface()

This commit is contained in:
Cameron Cawley
2026-05-13 20:51:02 +01:00
committed by Sam Lantinga
parent 9672f5b68b
commit c6b232f5d4
8 changed files with 175 additions and 6 deletions

View File

@@ -1285,3 +1285,5 @@ _SDL_SetGPURenderStateStorageBuffers
_SDL_GDKSuspendRenderer
_SDL_GDKResumeRenderer
_SDL_IsPhone
_SDL_LoadJPG_IO
_SDL_LoadJPG

View File

@@ -1286,6 +1286,8 @@ SDL3_0.0.0 {
SDL_GDKSuspendRenderer;
SDL_GDKResumeRenderer;
SDL_IsPhone;
SDL_LoadJPG_IO;
SDL_LoadJPG;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@@ -1312,3 +1312,5 @@
#define SDL_GDKSuspendRenderer SDL_GDKSuspendRenderer_REAL
#define SDL_GDKResumeRenderer SDL_GDKResumeRenderer_REAL
#define SDL_IsPhone SDL_IsPhone_REAL
#define SDL_LoadJPG_IO SDL_LoadJPG_IO_REAL
#define SDL_LoadJPG SDL_LoadJPG_REAL

View File

@@ -1320,3 +1320,5 @@ SDL_DYNAPI_PROC(bool,SDL_SetGPURenderStateStorageBuffers,(SDL_GPURenderState *a,
SDL_DYNAPI_PROC(void,SDL_GDKSuspendRenderer,(SDL_Renderer *a),(a),)
SDL_DYNAPI_PROC(void,SDL_GDKResumeRenderer,(SDL_Renderer *a),(a),)
SDL_DYNAPI_PROC(bool,SDL_IsPhone,(void),(),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadJPG_IO,(SDL_IOStream *a,bool b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadJPG,(const char *a),(a),return)

View File

@@ -363,6 +363,116 @@ static SDL_Surface *SDL_LoadSTB_IO(SDL_IOStream *src)
}
#endif // SDL_HAVE_STB
/* FIXME: This is a copypaste from JPEGLIB! Pull that out of the ifdefs */
/* Define this for quicker (but less perfect) JPEG identification */
#define FAST_IS_JPEG
/* See if an image is contained in a data source */
bool SDL_IsJPG(SDL_IOStream *src)
{
Sint64 start;
bool is_JPG;
bool in_scan;
Uint8 magic[4];
/* This detection code is by Steaphan Greene <stea@cs.binghamton.edu> */
/* Blame me, not Sam, if this doesn't work right. */
/* And don't forget to report the problem to the the sdl list too! */
if (!src) {
return false;
}
start = SDL_TellIO(src);
is_JPG = false;
in_scan = false;
if (SDL_ReadIO(src, magic, 2) == 2) {
if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) {
is_JPG = true;
while (is_JPG) {
if (SDL_ReadIO(src, magic, 2) != 2) {
is_JPG = false;
} else if ( (magic[0] != 0xFF) && !in_scan ) {
is_JPG = false;
} else if ( (magic[0] != 0xFF) || (magic[1] == 0xFF) ) {
/* Extra padding in JPEG (legal) */
/* or this is data and we are scanning */
SDL_SeekIO(src, -1, SDL_IO_SEEK_CUR);
} else if (magic[1] == 0xD9) {
/* Got to end of good JPEG */
break;
} else if ( in_scan && (magic[1] == 0x00) ) {
/* This is an encoded 0xFF within the data */
} else if ( (magic[1] >= 0xD0) && (magic[1] < 0xD9) ) {
/* These have nothing else */
} else if (SDL_ReadIO(src, magic+2, 2) != 2) {
is_JPG = false;
} else {
/* Yes, it's big-endian */
Sint64 innerStart;
Uint32 size;
Sint64 end;
innerStart = SDL_TellIO(src);
size = (magic[2] << 8) + magic[3];
end = SDL_SeekIO(src, size-2, SDL_IO_SEEK_CUR);
if ( end != innerStart + size - 2 ) {
is_JPG = false;
}
if ( magic[1] == 0xDA ) {
/* Now comes the actual JPEG meat */
#ifdef FAST_IS_JPEG
/* Ok, I'm convinced. It is a JPEG. */
break;
#else
/* I'm not convinced. Prove it! */
in_scan = true;
#endif
}
}
}
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
return is_JPG;
}
SDL_Surface *SDL_LoadJPG_IO(SDL_IOStream *src, bool closeio)
{
SDL_Surface *surface = NULL;
CHECK_PARAM(!src) {
SDL_InvalidParamError("src");
goto done;
}
if (!SDL_IsJPG(src)) {
SDL_SetError("File is not a JPEG file");
goto done;
}
#ifdef SDL_HAVE_STB
surface = SDL_LoadSTB_IO(src);
#else
SDL_SetError("SDL not built with STB image support");
#endif // SDL_HAVE_STB
done:
if (src && closeio) {
SDL_CloseIO(src);
}
return surface;
}
SDL_Surface *SDL_LoadJPG(const char *file)
{
SDL_IOStream *stream = SDL_IOFromFile(file, "rb");
if (!stream) {
return NULL;
}
return SDL_LoadJPG_IO(stream, true);
}
bool SDL_IsPNG(SDL_IOStream *src)
{
Sint64 start;

View File

@@ -3118,6 +3118,8 @@ SDL_Surface *SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio)
return SDL_LoadBMP_IO(src, closeio);
} else if (SDL_IsPNG(src)) {
return SDL_LoadPNG_IO(src, closeio);
} else if (SDL_IsJPG(src)) {
return SDL_LoadJPG_IO(src, closeio);
} else {
if (closeio) {
SDL_CloseIO(src);

View File

@@ -94,6 +94,7 @@ extern float SDL_GetSurfaceHDRHeadroom(SDL_Surface *surface, SDL_Colorspace colo
extern SDL_Surface *SDL_GetSurfaceImage(SDL_Surface *surface, float display_scale);
extern SDL_Surface *SDL_ConvertSurfaceRect(SDL_Surface *surface, const SDL_Rect *rect, SDL_PixelFormat format);
extern bool SDL_IsBMP(SDL_IOStream *src);
extern bool SDL_IsJPG(SDL_IOStream *src);
extern bool SDL_IsPNG(SDL_IOStream *src);
#endif // SDL_surface_c_h_