mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-14 15:42:49 +02:00
Support loading JPEG images through SDL_LoadSurface()
This commit is contained in:
committed by
Sam Lantinga
parent
9672f5b68b
commit
c6b232f5d4
@@ -29,10 +29,10 @@
|
||||
* provides a reasonable toolbox for transforming the data, including copying
|
||||
* between surfaces, filling rectangles in the image data, etc.
|
||||
*
|
||||
* There is also a simple .bmp loader, SDL_LoadBMP(), and a simple .png
|
||||
* loader, SDL_LoadPNG(). SDL itself does not provide loaders for other file
|
||||
* formats, but there are several excellent external libraries that do,
|
||||
* including its own satellite library,
|
||||
* There is also a simple .bmp loader, SDL_LoadBMP(), a simple .png loader,
|
||||
* SDL_LoadPNG(), and a simple .jpg loader, SDL_LoadJPG(). SDL itself does not
|
||||
* provide loaders for other file formats, but there are several excellent
|
||||
* external libraries that do, including its own satellite library,
|
||||
* [SDL_image](https://wiki.libsdl.org/SDL3_image)
|
||||
* .
|
||||
*
|
||||
@@ -510,7 +510,7 @@ 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.
|
||||
* Load a BMP, PNG or JPEG 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.
|
||||
@@ -531,7 +531,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
|
||||
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio);
|
||||
|
||||
/**
|
||||
* Load a BMP or PNG image from a file.
|
||||
* Load a BMP, PNG or JPEG image from a file.
|
||||
*
|
||||
* The new surface should be freed with SDL_DestroySurface(). Not doing so
|
||||
* will result in a memory leak.
|
||||
@@ -729,6 +729,54 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStre
|
||||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_SavePNG(SDL_Surface *surface, const char *file);
|
||||
|
||||
/**
|
||||
* Load a JPEG image from a seekable SDL data stream.
|
||||
*
|
||||
* This is intended as a convenience function for loading images from trusted
|
||||
* sources. If you want to load arbitrary images you should use libjpeg or
|
||||
* another image loading library designed with security in mind.
|
||||
*
|
||||
* 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.6.0.
|
||||
*
|
||||
* \sa SDL_DestroySurface
|
||||
* \sa SDL_LoadJPG
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadJPG_IO(SDL_IOStream *src, bool closeio);
|
||||
|
||||
/**
|
||||
* Load a JPEG image from a file.
|
||||
*
|
||||
* This is intended as a convenience function for loading images from trusted
|
||||
* sources. If you want to load arbitrary images you should use libjpeg or
|
||||
* another image loading library designed with security in mind.
|
||||
*
|
||||
* The new surface should be freed with SDL_DestroySurface(). Not doing so
|
||||
* will result in a memory leak.
|
||||
*
|
||||
* \param file the JPG 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.6.0.
|
||||
*
|
||||
* \sa SDL_DestroySurface
|
||||
* \sa SDL_LoadJPG_IO
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadJPG(const char *file);
|
||||
|
||||
/**
|
||||
* Set the RLE acceleration hint for a surface.
|
||||
*
|
||||
|
||||
@@ -1285,3 +1285,5 @@ _SDL_SetGPURenderStateStorageBuffers
|
||||
_SDL_GDKSuspendRenderer
|
||||
_SDL_GDKResumeRenderer
|
||||
_SDL_IsPhone
|
||||
_SDL_LoadJPG_IO
|
||||
_SDL_LoadJPG
|
||||
|
||||
@@ -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: *;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user