mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-26 12:27:44 +00:00
Added support for loading and saving PNG images using stb_image
This commit is contained in:
@@ -559,7 +559,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file);
|
|||||||
extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio);
|
extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a surface to a file.
|
* Save a surface to a file in BMP format.
|
||||||
*
|
*
|
||||||
* Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
|
* Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
|
||||||
* BMP directly. Other RGB formats with 8-bit or higher get converted to a
|
* BMP directly. Other RGB formats with 8-bit or higher get converted to a
|
||||||
@@ -581,6 +581,84 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStre
|
|||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file);
|
extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a 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.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_DestroySurface
|
||||||
|
* \sa SDL_LoadPNG
|
||||||
|
* \sa SDL_SavePNG_IO
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadPNG_IO(SDL_IOStream *src, bool closeio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a 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 PNG 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.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_DestroySurface
|
||||||
|
* \sa SDL_LoadPNG_IO
|
||||||
|
* \sa SDL_SavePNG
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadPNG(const char *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a surface to a seekable SDL data stream in PNG format.
|
||||||
|
*
|
||||||
|
* \param surface the SDL_Surface structure containing the image to be saved.
|
||||||
|
* \param dst a data stream to save to.
|
||||||
|
* \param closeio if true, calls SDL_CloseIO() on `dst` before returning, even
|
||||||
|
* in the case of an error.
|
||||||
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_LoadPNG_IO
|
||||||
|
* \sa SDL_SavePNG
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a surface to a file in PNG format.
|
||||||
|
*
|
||||||
|
* \param surface the SDL_Surface structure containing the image to be saved.
|
||||||
|
* \param file a file to save to.
|
||||||
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_LoadPNG
|
||||||
|
* \sa SDL_SavePNG_IO
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_SavePNG(SDL_Surface *surface, const char *file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the RLE acceleration hint for a surface.
|
* Set the RLE acceleration hint for a surface.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1260,6 +1260,10 @@ SDL3_0.0.0 {
|
|||||||
SDL_SetTexturePalette;
|
SDL_SetTexturePalette;
|
||||||
SDL_GetTexturePalette;
|
SDL_GetTexturePalette;
|
||||||
SDL_GetGPURendererDevice;
|
SDL_GetGPURendererDevice;
|
||||||
|
SDL_LoadPNG_IO;
|
||||||
|
SDL_LoadPNG;
|
||||||
|
SDL_SavePNG_IO;
|
||||||
|
SDL_SavePNG;
|
||||||
# extra symbols go here (don't modify this line)
|
# extra symbols go here (don't modify this line)
|
||||||
local: *;
|
local: *;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1286,3 +1286,7 @@
|
|||||||
#define SDL_SetTexturePalette SDL_SetTexturePalette_REAL
|
#define SDL_SetTexturePalette SDL_SetTexturePalette_REAL
|
||||||
#define SDL_GetTexturePalette SDL_GetTexturePalette_REAL
|
#define SDL_GetTexturePalette SDL_GetTexturePalette_REAL
|
||||||
#define SDL_GetGPURendererDevice SDL_GetGPURendererDevice_REAL
|
#define SDL_GetGPURendererDevice SDL_GetGPURendererDevice_REAL
|
||||||
|
#define SDL_LoadPNG_IO SDL_LoadPNG_IO_REAL
|
||||||
|
#define SDL_LoadPNG SDL_LoadPNG_REAL
|
||||||
|
#define SDL_SavePNG_IO SDL_SavePNG_IO_REAL
|
||||||
|
#define SDL_SavePNG SDL_SavePNG_REAL
|
||||||
|
|||||||
@@ -1294,3 +1294,7 @@ SDL_DYNAPI_PROC(Sint32,JNI_OnLoad,(JavaVM *a, void *b),(a,b),return)
|
|||||||
SDL_DYNAPI_PROC(bool,SDL_SetTexturePalette,(SDL_Texture *a,SDL_Palette *b),(a,b),return)
|
SDL_DYNAPI_PROC(bool,SDL_SetTexturePalette,(SDL_Texture *a,SDL_Palette *b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(SDL_Palette*,SDL_GetTexturePalette,(SDL_Texture *a),(a),return)
|
SDL_DYNAPI_PROC(SDL_Palette*,SDL_GetTexturePalette,(SDL_Texture *a),(a),return)
|
||||||
SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_GetGPURendererDevice,(SDL_Renderer *a),(a),return)
|
SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_GetGPURendererDevice,(SDL_Renderer *a),(a),return)
|
||||||
|
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadPNG_IO,(SDL_IOStream *a,bool b),(a,b),return)
|
||||||
|
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadPNG,(const char *a),(a),return)
|
||||||
|
SDL_DYNAPI_PROC(bool,SDL_SavePNG_IO,(SDL_Surface *a,SDL_IOStream *b,bool c),(a,b,c),return)
|
||||||
|
SDL_DYNAPI_PROC(bool,SDL_SavePNG,(SDL_Surface *a,const char *b),(a,b),return)
|
||||||
|
|||||||
@@ -48,12 +48,11 @@
|
|||||||
#if defined(SDL_NEON_INTRINSICS)
|
#if defined(SDL_NEON_INTRINSICS)
|
||||||
#define STBI_NEON
|
#define STBI_NEON
|
||||||
#endif
|
#endif
|
||||||
|
#define STBI_ONLY_PNG
|
||||||
#define STBI_ONLY_JPEG
|
#define STBI_ONLY_JPEG
|
||||||
#define STBI_NO_GIF
|
#define STBI_NO_GIF
|
||||||
#define STBI_NO_PNG
|
|
||||||
#define STBI_NO_HDR
|
#define STBI_NO_HDR
|
||||||
#define STBI_NO_LINEAR
|
#define STBI_NO_LINEAR
|
||||||
#define STBI_NO_ZLIB
|
|
||||||
#define STBI_NO_STDIO
|
#define STBI_NO_STDIO
|
||||||
#define STBI_ASSERT SDL_assert
|
#define STBI_ASSERT SDL_assert
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
@@ -127,6 +126,252 @@ bool SDL_ConvertPixels_STB(int width, int height,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_HAVE_STB
|
||||||
|
static int IMG_LoadSTB_IO_read(void *user, char *data, int size)
|
||||||
|
{
|
||||||
|
size_t amount = SDL_ReadIO((SDL_IOStream*)user, data, size);
|
||||||
|
return (int)amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IMG_LoadSTB_IO_skip(void *user, int n)
|
||||||
|
{
|
||||||
|
SDL_SeekIO((SDL_IOStream*)user, n, SDL_IO_SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int IMG_LoadSTB_IO_eof(void *user)
|
||||||
|
{
|
||||||
|
SDL_IOStream *src = (SDL_IOStream*)user;
|
||||||
|
return SDL_GetIOStatus(src) == SDL_IO_STATUS_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_Surface *SDL_LoadSTB_IO(SDL_IOStream *src)
|
||||||
|
{
|
||||||
|
Sint64 start;
|
||||||
|
Uint8 magic[26];
|
||||||
|
int w, h, format;
|
||||||
|
stbi_uc *pixels;
|
||||||
|
stbi_io_callbacks rw_callbacks;
|
||||||
|
SDL_Surface *surface = NULL;
|
||||||
|
bool use_palette = false;
|
||||||
|
unsigned int palette_colors[256];
|
||||||
|
|
||||||
|
// src has already been validated
|
||||||
|
start = SDL_TellIO(src);
|
||||||
|
|
||||||
|
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
|
||||||
|
const Uint8 PNG_COLOR_INDEXED = 3;
|
||||||
|
if (magic[0] == 0x89 &&
|
||||||
|
magic[1] == 'P' &&
|
||||||
|
magic[2] == 'N' &&
|
||||||
|
magic[3] == 'G' &&
|
||||||
|
magic[12] == 'I' &&
|
||||||
|
magic[13] == 'H' &&
|
||||||
|
magic[14] == 'D' &&
|
||||||
|
magic[15] == 'R' &&
|
||||||
|
magic[25] == PNG_COLOR_INDEXED) {
|
||||||
|
use_palette = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
|
||||||
|
|
||||||
|
/* Load the image data */
|
||||||
|
rw_callbacks.read = IMG_LoadSTB_IO_read;
|
||||||
|
rw_callbacks.skip = IMG_LoadSTB_IO_skip;
|
||||||
|
rw_callbacks.eof = IMG_LoadSTB_IO_eof;
|
||||||
|
w = h = format = 0; /* silence warning */
|
||||||
|
if (use_palette) {
|
||||||
|
/* Unused palette entries will be opaque white */
|
||||||
|
SDL_memset(palette_colors, 0xff, sizeof(palette_colors));
|
||||||
|
|
||||||
|
pixels = stbi_load_from_callbacks_with_palette(
|
||||||
|
&rw_callbacks,
|
||||||
|
src,
|
||||||
|
&w,
|
||||||
|
&h,
|
||||||
|
palette_colors,
|
||||||
|
SDL_arraysize(palette_colors)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
pixels = stbi_load_from_callbacks(
|
||||||
|
&rw_callbacks,
|
||||||
|
src,
|
||||||
|
&w,
|
||||||
|
&h,
|
||||||
|
&format,
|
||||||
|
STBI_default
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!pixels) {
|
||||||
|
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_palette) {
|
||||||
|
surface = SDL_CreateSurfaceFrom(
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
SDL_PIXELFORMAT_INDEX8,
|
||||||
|
pixels,
|
||||||
|
w
|
||||||
|
);
|
||||||
|
if (surface) {
|
||||||
|
bool has_colorkey = false;
|
||||||
|
int colorkey_index = -1;
|
||||||
|
bool has_alpha = false;
|
||||||
|
SDL_Palette *palette = SDL_CreateSurfacePalette(surface);
|
||||||
|
if (palette) {
|
||||||
|
int i;
|
||||||
|
Uint8 *palette_bytes = (Uint8 *)palette_colors;
|
||||||
|
|
||||||
|
for (i = 0; i < palette->ncolors; i++) {
|
||||||
|
palette->colors[i].r = *palette_bytes++;
|
||||||
|
palette->colors[i].g = *palette_bytes++;
|
||||||
|
palette->colors[i].b = *palette_bytes++;
|
||||||
|
palette->colors[i].a = *palette_bytes++;
|
||||||
|
if (palette->colors[i].a != SDL_ALPHA_OPAQUE) {
|
||||||
|
if (palette->colors[i].a == SDL_ALPHA_TRANSPARENT && !has_colorkey) {
|
||||||
|
has_colorkey = true;
|
||||||
|
colorkey_index = i;
|
||||||
|
} else {
|
||||||
|
/* Partial opacity or multiple colorkeys */
|
||||||
|
has_alpha = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_alpha) {
|
||||||
|
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
|
||||||
|
} else if (has_colorkey) {
|
||||||
|
SDL_SetSurfaceColorKey(surface, true, colorkey_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: This sucks. It'd be better to allocate the surface first, then
|
||||||
|
* write directly to the pixel buffer:
|
||||||
|
* https://github.com/nothings/stb/issues/58
|
||||||
|
* -flibit
|
||||||
|
*/
|
||||||
|
surface->flags &= ~SDL_SURFACE_PREALLOCATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (format == STBI_grey || format == STBI_rgb || format == STBI_rgb_alpha) {
|
||||||
|
surface = SDL_CreateSurfaceFrom(
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
(format == STBI_rgb_alpha) ? SDL_PIXELFORMAT_RGBA32 :
|
||||||
|
(format == STBI_rgb) ? SDL_PIXELFORMAT_RGB24 :
|
||||||
|
SDL_PIXELFORMAT_INDEX8,
|
||||||
|
pixels,
|
||||||
|
w * format
|
||||||
|
);
|
||||||
|
if (surface) {
|
||||||
|
/* Set a grayscale palette for gray images */
|
||||||
|
if (surface->format == SDL_PIXELFORMAT_INDEX8) {
|
||||||
|
SDL_Palette *palette = SDL_CreateSurfacePalette(surface);
|
||||||
|
if (palette) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < palette->ncolors; i++) {
|
||||||
|
palette->colors[i].r = (Uint8)i;
|
||||||
|
palette->colors[i].g = (Uint8)i;
|
||||||
|
palette->colors[i].b = (Uint8)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: This sucks. It'd be better to allocate the surface first, then
|
||||||
|
* write directly to the pixel buffer:
|
||||||
|
* https://github.com/nothings/stb/issues/58
|
||||||
|
* -flibit
|
||||||
|
*/
|
||||||
|
surface->flags &= ~SDL_SURFACE_PREALLOCATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (format == STBI_grey_alpha) {
|
||||||
|
surface = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_RGBA32);
|
||||||
|
if (surface) {
|
||||||
|
Uint8 *src_ptr = pixels;
|
||||||
|
Uint8 *dst = (Uint8 *)surface->pixels;
|
||||||
|
int skip = surface->pitch - (surface->w * 4);
|
||||||
|
int row, col;
|
||||||
|
|
||||||
|
for (row = 0; row < h; ++row) {
|
||||||
|
for (col = 0; col < w; ++col) {
|
||||||
|
Uint8 c = *src_ptr++;
|
||||||
|
Uint8 a = *src_ptr++;
|
||||||
|
*dst++ = c;
|
||||||
|
*dst++ = c;
|
||||||
|
*dst++ = c;
|
||||||
|
*dst++ = a;
|
||||||
|
}
|
||||||
|
dst += skip;
|
||||||
|
}
|
||||||
|
stbi_image_free(pixels);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SDL_SetError("Unknown image format: %d", format);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!surface) {
|
||||||
|
/* The error message should already be set */
|
||||||
|
stbi_image_free(pixels); /* calls SDL_free() */
|
||||||
|
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
|
||||||
|
}
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
#endif // SDL_HAVE_STB
|
||||||
|
|
||||||
|
SDL_Surface *SDL_LoadPNG_IO(SDL_IOStream *src, bool closeio)
|
||||||
|
{
|
||||||
|
Sint64 start;
|
||||||
|
Uint8 magic[4];
|
||||||
|
bool is_PNG;
|
||||||
|
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) {
|
||||||
|
SDL_SetError("File is not a PNG 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_LoadPNG(const char *file)
|
||||||
|
{
|
||||||
|
SDL_IOStream *stream = SDL_IOFromFile(file, "rb");
|
||||||
|
if (!stream) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_LoadPNG_IO(stream, true);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SDL_HAVE_STB
|
#ifdef SDL_HAVE_STB
|
||||||
static void SDL_STBWriteFunc(void *context, void *data, int size)
|
static void SDL_STBWriteFunc(void *context, void *data, int size)
|
||||||
{
|
{
|
||||||
@@ -136,46 +381,46 @@ static void SDL_STBWriteFunc(void *context, void *data, int size)
|
|||||||
|
|
||||||
bool SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio)
|
bool SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio)
|
||||||
{
|
{
|
||||||
#ifdef SDL_HAVE_STB
|
bool retval = false;
|
||||||
bool retval = true;
|
|
||||||
|
|
||||||
// Make sure we have somewhere to save
|
// Make sure we have somewhere to save
|
||||||
CHECK_PARAM(!SDL_SurfaceValid(surface)) {
|
CHECK_PARAM(!SDL_SurfaceValid(surface)) {
|
||||||
retval = SDL_InvalidParamError("surface");
|
SDL_InvalidParamError("surface");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
CHECK_PARAM(!dst) {
|
CHECK_PARAM(!dst) {
|
||||||
retval = SDL_InvalidParamError("dst");
|
SDL_InvalidParamError("dst");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_HAVE_STB
|
||||||
bool free_surface = false;
|
bool free_surface = false;
|
||||||
if (surface->format != SDL_PIXELFORMAT_ABGR8888) {
|
if (surface->format != SDL_PIXELFORMAT_RGBA32) {
|
||||||
surface = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888);
|
surface = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32);
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
retval = false;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
free_surface = true;
|
free_surface = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stbi_write_png_to_func(SDL_STBWriteFunc, dst, surface->w, surface->h, 4, surface->pixels, surface->pitch)) {
|
if (stbi_write_png_to_func(SDL_STBWriteFunc, dst, surface->w, surface->h, 4, surface->pixels, surface->pitch)) {
|
||||||
retval = SDL_SetError("Failed to write PNG");
|
retval = true;
|
||||||
|
} else {
|
||||||
|
SDL_SetError("Failed to write PNG");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (free_surface) {
|
if (free_surface) {
|
||||||
SDL_DestroySurface(surface);
|
SDL_DestroySurface(surface);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
SDL_SetError("SDL not built with STB image support");
|
||||||
|
#endif
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (dst && closeio) {
|
if (dst && closeio) {
|
||||||
retval = SDL_CloseIO(dst);
|
retval &= SDL_CloseIO(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
#else
|
|
||||||
return SDL_SetError("SDL not built with STB image write support");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL_SavePNG(SDL_Surface *surface, const char *file)
|
bool SDL_SavePNG(SDL_Surface *surface, const char *file)
|
||||||
@@ -188,6 +433,6 @@ bool SDL_SavePNG(SDL_Surface *surface, const char *file)
|
|||||||
|
|
||||||
return SDL_SavePNG_IO(surface, stream, true);
|
return SDL_SavePNG_IO(surface, stream, true);
|
||||||
#else
|
#else
|
||||||
return SDL_SetError("SDL not built with STB image write support");
|
return SDL_SetError("SDL not built with STB image support");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,5 @@
|
|||||||
// Image conversion functions
|
// Image conversion functions
|
||||||
|
|
||||||
extern bool SDL_ConvertPixels_STB(int width, int height, SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
|
extern bool SDL_ConvertPixels_STB(int width, int height, SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
|
||||||
extern bool SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio);
|
|
||||||
extern bool SDL_SavePNG(SDL_Surface *surface, const char *file);
|
|
||||||
|
|
||||||
#endif // SDL_stb_c_h_
|
#endif // SDL_stb_c_h_
|
||||||
|
|||||||
@@ -453,8 +453,8 @@ STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wch
|
|||||||
|
|
||||||
#if 0 /* not used in SDL */
|
#if 0 /* not used in SDL */
|
||||||
STBIDEF stbi_uc *stbi_load_from_memory_with_palette (stbi_uc const *buffer, int len , int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len);
|
STBIDEF stbi_uc *stbi_load_from_memory_with_palette (stbi_uc const *buffer, int len , int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len);
|
||||||
STBIDEF stbi_uc *stbi_load_from_callbacks_with_palette(stbi_io_callbacks const *clbk, void *user, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len);
|
|
||||||
#endif
|
#endif
|
||||||
|
STBIDEF stbi_uc *stbi_load_from_callbacks_with_palette(stbi_io_callbacks const *clbk, void *user, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len);
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
//
|
//
|
||||||
@@ -559,14 +559,18 @@ STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_fli
|
|||||||
// ZLIB client - used by PNG, available for other purposes
|
// ZLIB client - used by PNG, available for other purposes
|
||||||
|
|
||||||
#ifndef STBI_NO_ZLIB
|
#ifndef STBI_NO_ZLIB
|
||||||
|
#if 0 /* not used in SDL */
|
||||||
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
|
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
|
||||||
|
#endif
|
||||||
STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
|
STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
|
||||||
|
#if 0 /* not used in SDL */
|
||||||
STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
|
STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
|
||||||
STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
||||||
|
|
||||||
STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
|
STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
|
||||||
STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -897,7 +901,6 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
|
|||||||
s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
|
s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* not used in SDL */
|
|
||||||
// initialize a callback-based context
|
// initialize a callback-based context
|
||||||
static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
|
static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
|
||||||
{
|
{
|
||||||
@@ -910,7 +913,6 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
|
|||||||
stbi__refill_buffer(s);
|
stbi__refill_buffer(s);
|
||||||
s->img_buffer_original_end = s->img_buffer_end;
|
s->img_buffer_original_end = s->img_buffer_end;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STBI_NO_STDIO
|
#ifndef STBI_NO_STDIO
|
||||||
|
|
||||||
@@ -1353,7 +1355,6 @@ static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int byt
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0 /* not used in SDL */
|
|
||||||
static unsigned char *stbi__load_indexed(stbi__context *s, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len)
|
static unsigned char *stbi__load_indexed(stbi__context *s, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len)
|
||||||
{
|
{
|
||||||
stbi__result_info ri;
|
stbi__result_info ri;
|
||||||
@@ -1386,7 +1387,6 @@ static unsigned char *stbi__load_indexed(stbi__context *s, int *x, int *y, unsig
|
|||||||
|
|
||||||
return (unsigned char *) result;
|
return (unsigned char *) result;
|
||||||
}
|
}
|
||||||
#endif /**/
|
|
||||||
|
|
||||||
static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
||||||
{
|
{
|
||||||
@@ -1568,7 +1568,6 @@ STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, i
|
|||||||
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
|
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* not used in SDL */
|
|
||||||
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
|
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
|
||||||
{
|
{
|
||||||
stbi__context s;
|
stbi__context s;
|
||||||
@@ -1576,12 +1575,14 @@ STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *u
|
|||||||
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
|
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* not used in SDL */
|
||||||
STBIDEF stbi_uc *stbi_load_from_memory_with_palette(stbi_uc const *buffer, int len, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len)
|
STBIDEF stbi_uc *stbi_load_from_memory_with_palette(stbi_uc const *buffer, int len, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len)
|
||||||
{
|
{
|
||||||
stbi__context s;
|
stbi__context s;
|
||||||
stbi__start_mem(&s, buffer, len);
|
stbi__start_mem(&s, buffer, len);
|
||||||
return stbi__load_indexed(&s, x, y, palette_buffer, palette_buffer_len);
|
return stbi__load_indexed(&s, x, y, palette_buffer, palette_buffer_len);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
STBIDEF stbi_uc *stbi_load_from_callbacks_with_palette(stbi_io_callbacks const *clbk, void *user, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len)
|
STBIDEF stbi_uc *stbi_load_from_callbacks_with_palette(stbi_io_callbacks const *clbk, void *user, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len)
|
||||||
{
|
{
|
||||||
@@ -1589,7 +1590,6 @@ STBIDEF stbi_uc *stbi_load_from_callbacks_with_palette(stbi_io_callbacks const *
|
|||||||
stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
|
stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
|
||||||
return stbi__load_indexed(&s, x, y, palette_buffer, palette_buffer_len);
|
return stbi__load_indexed(&s, x, y, palette_buffer, palette_buffer_len);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STBI_NO_GIF
|
#ifndef STBI_NO_GIF
|
||||||
STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
|
STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
|
||||||
@@ -4735,6 +4735,7 @@ static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse
|
|||||||
return stbi__parse_zlib(a, parse_header);
|
return stbi__parse_zlib(a, parse_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* not used in SDL */
|
||||||
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
|
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
|
||||||
{
|
{
|
||||||
stbi__zbuf a;
|
stbi__zbuf a;
|
||||||
@@ -4755,6 +4756,7 @@ STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
|
|||||||
{
|
{
|
||||||
return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
|
return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
|
||||||
}
|
}
|
||||||
|
#endif /* */
|
||||||
|
|
||||||
STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
|
STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
|
||||||
{
|
{
|
||||||
@@ -4772,6 +4774,7 @@ STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* not used in SDL */
|
||||||
STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
|
STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
|
||||||
{
|
{
|
||||||
stbi__zbuf a;
|
stbi__zbuf a;
|
||||||
@@ -4809,6 +4812,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char
|
|||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif /* */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18
|
// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18
|
||||||
|
|||||||
@@ -1335,6 +1335,10 @@ const static struct {
|
|||||||
SDL_SYMBOL_ITEM(SDL_SetTexturePalette),
|
SDL_SYMBOL_ITEM(SDL_SetTexturePalette),
|
||||||
SDL_SYMBOL_ITEM(SDL_GetTexturePalette),
|
SDL_SYMBOL_ITEM(SDL_GetTexturePalette),
|
||||||
SDL_SYMBOL_ITEM(SDL_GetGPURendererDevice),
|
SDL_SYMBOL_ITEM(SDL_GetGPURendererDevice),
|
||||||
|
SDL_SYMBOL_ITEM(SDL_LoadPNG_IO),
|
||||||
|
SDL_SYMBOL_ITEM(SDL_LoadPNG),
|
||||||
|
SDL_SYMBOL_ITEM(SDL_SavePNG_IO),
|
||||||
|
SDL_SYMBOL_ITEM(SDL_SavePNG),
|
||||||
/* extra symbols go here (don't modify this line) */
|
/* extra symbols go here (don't modify this line) */
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user