From 7224b4040776a4f6fa51905771d2c438e65d5ca7 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 22 Feb 2025 12:22:44 -0800
Subject: [PATCH] Fix errors when building stb_image with -DSDL_LIBC=OFF
I integrated changes from SDL_image and updated as needed for JPEG memory loading functionality.
Fixes https://github.com/libsdl-org/SDL/issues/12364
---
src/video/SDL_stb.c | 6 +-
src/video/stb_image.h | 293 ++++++++++++++++++++++++++++++++----------
2 files changed, 226 insertions(+), 73 deletions(-)
diff --git a/src/video/SDL_stb.c b/src/video/SDL_stb.c
index cbc822d84334a..934c1addff54b 100644
--- a/src/video/SDL_stb.c
+++ b/src/video/SDL_stb.c
@@ -42,8 +42,8 @@
#define pow SDL_pow
#define ldexp SDL_scalbn
-#define STB_INTERNAL_SDL
#define STB_IMAGE_STATIC
+#define STBI_NO_THREAD_LOCALS
#define STBI_FAILURE_USERMSG
#if defined(SDL_NEON_INTRINSICS)
#define STBI_NEON
@@ -84,7 +84,7 @@ static bool SDL_ConvertPixels_MJPG_to_NV12(int width, int height, const void *sr
void *pixels = stbi__jpeg_load(&s, &w, &h, &format, 4, &nv12, &ri);
if (!pixels) {
- return SDL_SetError("Couldn't decode image: %s", stbi_failure_reason());
+ return false;
}
return true;
}
@@ -104,7 +104,7 @@ bool SDL_ConvertPixels_STB(int width, int height,
int len = (src_format == SDL_PIXELFORMAT_MJPG) ? src_pitch : (height * src_pitch);
void *pixels = stbi_load_from_memory(src, len, &w, &h, &format, 4);
if (!pixels) {
- return SDL_SetError("Couldn't decode image: %s", stbi_failure_reason());
+ return false;
}
if (w == width && h == height) {
diff --git a/src/video/stb_image.h b/src/video/stb_image.h
index 62c1186246904..f5fd6ca9323e7 100644
--- a/src/video/stb_image.h
+++ b/src/video/stb_image.h
@@ -94,7 +94,7 @@ RECENT REVISION HISTORY:
Optimizations & bugfixes Mikhail Morozov (1-bit BMP)
Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query)
Arseny Kapoulkine Simon Breuss (16-bit PNM)
- John-Mark Allen
+ John-Mark Allen Katelyn Gadd (indexed color loading)
Carmelo J Fdez-Aguera
Bug & warning fixes
@@ -383,9 +383,14 @@ enum
STBI_rgb_alpha = 4
};
+#if 0 /* SDL change */
#include <stdlib.h>
typedef unsigned char stbi_uc;
typedef unsigned short stbi_us;
+#else
+typedef Uint8 stbi_uc;
+typedef Uint16 stbi_us;
+#endif
#ifdef __cplusplus
extern "C" {
@@ -421,7 +426,7 @@ typedef struct
//
STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
-#ifndef STB_INTERNAL_SDL
+#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 *channels_in_file, int desired_channels);
#endif
@@ -439,12 +444,24 @@ STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int *
STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
#endif
+////////////////////////////////////
+//
+// 8-bits-per-channel indexed color
+// Will fail if image is not an 8-bit PNG or TGA with a palette.
+// Palette buffer needs to be at least 256 entries for PNG.
+//
+
+#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_callbacks_with_palette(stbi_io_callbacks const *clbk, void *user, int *x, int *y, unsigned int *palette_buffer, int palette_buffer_len);
+#endif
+
////////////////////////////////////
//
// 16-bits-per-channel interface
//
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
#endif
@@ -478,7 +495,7 @@ STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_i
STBIDEF void stbi_ldr_to_hdr_scale(float scale);
#endif // STBI_NO_LINEAR
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
@@ -489,15 +506,17 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f);
#endif // STBI_NO_STDIO
+#if 0 /* not used in SDL */
// get a VERY brief reason for failure
// on most compilers (and ALL modern mainstream compilers) this is threadsafe
STBIDEF const char *stbi_failure_reason (void);
+#endif
// free the loaded image -- this is just free()
STBIDEF void stbi_image_free (void *retval_from_stbi_load);
+#if 0 /* not used in SDL */
// get image dimensions & components without fully decoding
-#ifndef STB_INTERNAL_SDL
STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
@@ -512,8 +531,8 @@ STBIDEF int stbi_is_16_bit_from_file(FILE *f);
#endif
-
#ifndef STBI_NO_PNG
+#if 0 /* not used in SDL */
// for image formats that explicitly notate that they have premultiplied alpha,
// we just return the colors as stored in the file. set this flag to force
// unpremultiplication. results are undefined if the unpremultiply overflow.
@@ -525,7 +544,9 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// flip the image vertically, so the first pixel in the output array is the bottom left
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
+#endif /**/
+#ifndef STBI_NO_THREAD_LOCALS /**/
// as above, but only applies to images loaded on the thread that calls the function
// this function is only available if your compiler supports thread-local variables;
// calling it will fail to link if your compiler doesn't
@@ -533,6 +554,7 @@ STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpre
STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert);
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
#endif
+#endif
// ZLIB client - used by PNG, available for other purposes
@@ -596,6 +618,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#endif
+#if 0 /* SDL change */
#include <stdarg.h>
#include <stddef.h> // ptrdiff_t on osx
#include <stdlib.h>
@@ -605,6 +628,23 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
#include <math.h> // ldexp, pow
#endif
+#else /* SDL change */
+#ifndef UINT_MAX
+#define UINT_MAX SDL_MAX_UINT32
+#endif
+#ifndef INT_MAX
+#define INT_MAX SDL_MAX_SINT32
+#endif
+#ifndef INT_MIN
+#define INT_MIN SDL_MIN_SINT32
+#endif
+#ifndef SHRT_MAX
+#define SHRT_MAX SDL_MAX_SINT16
+#endif
+#ifndef SHRT_MIN
+#define SHRT_MIN SDL_MIN_SINT16
+#endif
+#endif
#ifndef STBI_NO_STDIO
#include <stdio.h>
@@ -650,6 +690,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#endif
#endif
+#if 0 /* SDL change */
#if defined(_MSC_VER) || defined(__SYMBIAN32__)
typedef unsigned short stbi__uint16;
typedef signed short stbi__int16;
@@ -662,6 +703,16 @@ typedef int16_t stbi__int16;
typedef uint32_t stbi__uint32;
typedef int32_t stbi__int32;
#endif
+#else
+typedef Uint16 stbi__uint16;
+typedef Sint16 stbi__int16;
+typedef Uint32 stbi__uint32;
+typedef Sint32 stbi__int32;
+#endif
+
+#ifndef STBI_BUFFER_SIZE
+#define STBI_BUFFER_SIZE 128
+#endif
// should produce compiler error if size is wrong
typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
@@ -672,9 +723,11 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
#define STBI_NOTUSED(v) (void)sizeof(v)
#endif
+#if 0 /* SDL change: */
#ifdef _MSC_VER
#define STBI_HAS_LROTL
#endif
+#endif
#ifdef STBI_HAS_LROTL
#define stbi_lrot(x,y) _lrotl(x,y)
@@ -844,8 +897,8 @@ 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;
}
+#if 0 /* not used in SDL */
// initialize a callback-based context
-#ifndef STB_INTERNAL_SDL
static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
{
s->io = *c;
@@ -857,7 +910,7 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
stbi__refill_buffer(s);
s->img_buffer_original_end = s->img_buffer_end;
}
-#endif // !STB_INTERNAL_SDL
+#endif
#ifndef STBI_NO_STDIO
@@ -931,17 +984,19 @@ typedef struct
#ifndef STBI_NO_JPEG
static int stbi__jpeg_test(stbi__context *s);
static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__nv12 *nv12, stbi__result_info *ri);
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#endif
#ifndef STBI_NO_PNG
static int stbi__png_test(stbi__context *s);
-static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, unsigned int *palette_buffer, int palette_buffer_len, stbi__result_info *ri);
+#if 0 /* not used in SDL */
static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
static int stbi__png_is16(stbi__context *s);
#endif
+#endif
#ifndef STBI_NO_BMP
static int stbi__bmp_test(stbi__context *s);
@@ -951,7 +1006,7 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
#ifndef STBI_NO_TGA
static int stbi__tga_test(stbi__context *s);
-static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, unsigned int *palette_buffer, int palette_buffer_len, stbi__result_info *ri);
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
#endif
@@ -988,6 +1043,14 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
static int stbi__pnm_is16(stbi__context *s);
#endif
+#ifndef STBI_NO_FAILURE_STRINGS
+#if 1 /* SDL change: */
+static int stbi__err(const char *str)
+{
+ SDL_SetError("%s", str);
+ return 0;
+}
+#else /* SDL change. */
static
#ifdef STBI_THREAD_LOCAL
STBI_THREAD_LOCAL
@@ -999,12 +1062,12 @@ STBIDEF const char *stbi_failure_reason(void)
return stbi__g_failure_reason;
}
-#ifndef STBI_NO_FAILURE_STRINGS
static int stbi__err(const char *str)
{
stbi__g_failure_reason = str;
return 0;
}
+#endif /**/
#endif
static void *stbi__malloc(size_t size)
@@ -1139,10 +1202,12 @@ static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
static int stbi__vertically_flip_on_load_global = 0;
#ifndef STBI_NO_PNG
+#if 0 /* not used in SDL */
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
}
+#endif /**/
#endif
#ifndef STBI_THREAD_LOCAL
@@ -1163,7 +1228,7 @@ STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_fli
: stbi__vertically_flip_on_load_global)
#endif // STBI_THREAD_LOCAL
-static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc, unsigned int *palette_buffer, int palette_buffer_len)
{
memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
@@ -1173,7 +1238,7 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
// test the formats with a very explicit header first (at least a FOURCC
// or distinctive magic number first)
#ifndef STBI_NO_PNG
- if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri);
+ if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, palette_buffer, palette_buffer_len, ri);
#endif
#ifndef STBI_NO_BMP
if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri);
@@ -1194,7 +1259,7 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
// bytes matching expectations; these are prone to false positives, so
// try them later
#ifndef STBI_NO_JPEG
- if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp,0, ri);
+ if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp,NULL, ri);
#endif
#ifndef STBI_NO_PNM
if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri);
@@ -1210,7 +1275,7 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
#ifndef STBI_NO_TGA
// test tga last because it's a crappy test!
if (stbi__tga_test(s))
- return stbi__tga_load(s,x,y,comp,req_comp, ri);
+ return stbi__tga_load(s,x,y,comp,req_comp, palette_buffer, palette_buffer_len, ri);
#endif
return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
@@ -1232,7 +1297,7 @@ static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int chan
return reduced;
}
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
{
int i;
@@ -1248,7 +1313,7 @@ static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int chan
STBI_FREE(orig);
return enlarged;
}
-#endif // !STB_INTERNAL_SDL
+#endif
static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
{
@@ -1288,10 +1353,45 @@ static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int byt
}
#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)
+{
+ stbi__result_info ri;
+ int comp;
+ void *result;
+
+ if (!palette_buffer)
+ return NULL;
+
+ result = stbi__load_main(s, x, y, &comp, 1, &ri, 8, palette_buffer, palette_buffer_len);
+ if (result == NULL)
+ return NULL;
+
+ if (comp != 1) {
+ stbi_image_free(result);
+ return NULL;
+ }
+
+ if (ri.bits_per_channel != 8) {
+ stbi_image_free(result);
+ return NULL;
+ }
+
+ // @TODO: move stbi__convert_format to here
+
+ if (stbi__vertically_flip_on_load) {
+ int channels = 1;
+ stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
+ }
+
+ 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)
{
stbi__result_info ri;
- void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8, NULL, 0);
if (result == NULL)
return NULL;
@@ -1314,11 +1414,11 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x,
return (unsigned char *) result;
}
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
stbi__result_info ri;
- void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16, NULL, 0);
if (result == NULL)
return NULL;
@@ -1341,7 +1441,7 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
return (stbi__uint16 *) result;
}
-#endif // !STB_INTERNAL_SDL
+#endif /**/
#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR)
static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
@@ -1445,7 +1545,7 @@ STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, i
#endif //!STBI_NO_STDIO
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
{
stbi__context s;
@@ -1459,7 +1559,7 @@ STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void
stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
}
-#endif
+#endif /**/
STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
{
@@ -1468,13 +1568,27 @@ 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);
}
-#ifndef STB_INTERNAL_SDL
+#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)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
}
+
+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__start_mem(&s, buffer, len);
+ return stbi__load_indexed(&s, x, y, palette_buffer, 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)
+{
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+ return stbi__load_indexed(&s, x, y, palette_buffer, palette_buffer_len);
+}
#endif
#ifndef STBI_NO_GIF
@@ -1547,11 +1661,11 @@ STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_
#endif // !STBI_NO_LINEAR
+#if 0 /* not used in SDL */
// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is
// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always
// reports false!
-#ifndef STB_INTERNAL_SDL
STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
{
#ifndef STBI_NO_HDR
@@ -1564,7 +1678,7 @@ STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
return 0;
#endif
}
-#endif // !STB_INTERNAL_SDL
+#endif
#ifndef STBI_NO_STDIO
STBIDEF int stbi_is_hdr (char const *filename)
@@ -1595,7 +1709,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f)
}
#endif // !STBI_NO_STDIO
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user)
{
#ifndef STBI_NO_HDR
@@ -1608,7 +1722,7 @@ STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void
return 0;
#endif
}
-#endif // !STB_INTERNAL_SDL
+#endif
#ifndef STBI_NO_LINEAR
static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
@@ -2628,7 +2742,7 @@ static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
b = _mm_unpackhi_epi16(tmp, b)
#define dct_pass(bias,shift) \
- { \
+ do { \
/* even part */ \
dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \
__m128i sum04 = _mm_add_epi16(row0, row4); \
@@ -2653,7 +2767,7 @@ static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
dct_bfly32o(row1,row6, x1,x6,bias,shift); \
dct_bfly32o(row2,row5, x2,x5,bias,shift); \
dct_bfly32o(row3,row4, x3,x4,bias,shift); \
- }
+ } while ( 0 )
__m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));
__m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f));
@@ -2792,15 +2906,15 @@ static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
// butterfly a/b, then shift using "shiftop" by "s" and pack
#define dct_bfly32o(out0,out1, a,b,shiftop,s) \
- { \
+ do { \
dct_wadd(sum, a, b); \
dct_wsub(dif, a, b); \
out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \
out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \
- }
+ } while ( 0 )
#define dct_pass(shiftop, shift) \
- { \
+ do { \
/* even part */ \
int16x8_t sum26 = vaddq_s16(row2, row6); \
dct_long_mul(p1e, sum26, rot0_0); \
@@ -2837,7 +2951,7 @@ static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \
dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \
dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \
- }
+ } while ( 0 )
// load
row0 = vld1q_s16(data + 0*8);
@@ -2859,9 +2973,9 @@ static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
{
// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively.
// whether compilers actually get this is another story, sadly.
-#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; }
-#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); }
-#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); }
+#define dct_trn16(x, y) do { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } while ( 0 )
+#define dct_trn32(x, y) do { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } while ( 0 )
+#define dct_trn64(x, y) do { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } while ( 0 )
// pass 1
dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
@@ -2904,9 +3018,9 @@ static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
uint8x8_t p7 = vqrshrun_n_s16(row7, 1);
// again, these can translate into one instruction, but often don't.
-#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; }
-#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); }
-#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); }
+#define dct_trn8_8(x, y) do { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } while ( 0 )
+#define dct_trn8_16(x, y) do { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } while ( 0 )
+#define dct_trn8_32(x, y) do { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } while ( 0 )
// sadly can't use interleaved stores here since we only write
// 8 bytes to each scan line!
@@ -3876,9 +3990,11 @@ static void stbi__setup_jpeg(stbi__jpeg *j)
#endif
#ifdef STBI_NEON
+ if (SDL_HasNEON()) { /* SDL change */
j->idct_block_kernel = stbi__idct_simd;
j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+ } /**/
#endif
}
@@ -4152,7 +4268,7 @@ static int stbi__jpeg_test(stbi__context *s)
return r;
}
-#ifndef STB_INTERNAL_SDL
+#if 0 /* not used in SDL */
static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
{
if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {
@@ -4176,7 +4292,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
STBI_FREE(j);
return result;
}
-#endif // !STB_INTERNAL_SDL
+#endif /**/
#endif
// public domain zlib decode v0.2 Sean Barrett 2006-11-18
@@ -5094,6 +5210,7 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
static int stbi__unpremultiply_on_load_global = 0;
static int stbi__de_iphone_flag_global = 0;
+#if 0 /* not used in SDL */
STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
{
stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply;
@@ -5103,6 +5220,7 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
{
stbi__de_iphone_flag_global = flag_true_if_should_convert;
}
+#endif
#ifndef STBI_THREAD_LOCAL
#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global
@@ -5176,15 +5294,25 @@ static void stbi__de_iphone(stbi__png *z)
#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))
-static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
+static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp, unsigned int *palette_buffer, int palette_buffer_len)
{
- stbi_uc palette[1024], pal_img_n=0;
+ stbi_uc _palette[1024], pal_img_n=0;
+ stbi_uc *palette = _palette;
stbi_uc has_trans=0, tc[3]={0};
stbi__uint16 tc16[3];
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
int first=1,k,interlace=0, color=0, is_iphone=0;
stbi__context *s = z->s;
+ if (palette_buffer) {
+ if (palette_buffer_len < 256)
+ return stbi__err("palette buffer too small", "palette buffer len must be 256");
+ else if (req_comp != 1)
+ return stbi__err("invalid req_comp", "req_comp must be 1 when loading paletted");
+ else
+ palette = (stbi_uc *)(void *)palette_buffer;
+ }
+
z->expanded = NULL;
z->idata = NULL;
z->out = NULL;
@@ -5327,8 +5455,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
s->img_n = pal_img_n; // record the actual colors we had
s->img_out_n = pal_img_n;
if (req_comp >= 3) s->img_out_n = req_comp;
- if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
- return 0;
+ if (!palette_buffer)
+ if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
+ return 0;
} else if (has_trans) {
// non-paletted image with tRNS -> source image has (constant) alpha
++s->img_n;
@@ -5350,6 +5479,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);
invalid_chunk[2] = STBI__BYTECAST(c.type >> 8);
invalid_chunk[3] = STBI__BYTECAST(c.type >> 0);
+ (void)invalid_chunk;
#endif
return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");
}
@@ -5361,11 +5491,18 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
}
}
-static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
+static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, unsigned int *palette_buffer, int palette_buffer_len, stbi__result_info *ri)
{
void *result=NULL;
- if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
- if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
+ if (palette_buffer && req_comp != 1) {
+ stbi__err("bad req_comp", "req_comp must be 1 if loading paletted image without expansion");
+ return NULL;
+ }
+ if (req_comp < 0 || req_comp > 4) {
+ stbi__err("bad req_comp", "Internal error");
+ return NULL;
+ }
+ if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp, palette_buffer, palette_buffer_len)) {
if (p->depth <= 8)
ri->bits_per_channel = 8;
else if (p->depth == 16)
@@ -5375,7 +5512,9 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st
result = p->out;
p->out = NULL;
if (req_comp && req_comp != p->s->img_out_n) {
- if (ri->bits_per_channel == 8)
+ if (palette_buffer)
+ ;
+ else if (ri->bits_per_channel == 8)
result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
else
result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
@@ -5384,7 +5523,12 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st
}
*x = p->s->img_x;
*y = p->s->img_y;
- if (n) *n = p->s->img_n;
+ if (n) {
+ if (palette_buffer)
+ *n = 1;
+ else
+ *n = p->s->img_n;
+ }
}
STBI_FREE(p->out); p->out = NULL;
STBI_FREE(p->expanded); p->expanded = NULL;
@@ -5393,11 +5537,11 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st
return result;
}
-static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, unsigned int *palette_buffer, int palette_buffer_len, stbi__result_info *ri)
{
stbi__png p;
p.s = s;
- return stbi__do_png(&p, x,y,comp,req_comp, ri);
+ return stbi__do_png(&p, x,y,comp,req_comp, palette_buffer, palette_buffer_len, ri);
}
static int stbi__png_test(stbi__context *s)
@@ -5408,9 +5552,10 @@ static int stbi__png_test(stbi__context *s)
return r;
}
+#if 0 /* not used in SDL */
static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp)
{
- if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {
+ if (!stbi__parse_png_file(p, STBI__SCAN_header, NULL, 0, NULL)) {
stbi__rewind( p->s );
return 0;
}
@@ -5439,6 +5584,7 @@ static int stbi__png_is16(stbi__context *s)
}
return 1;
}
+#endif /**/
#endif
// Microsoft/Windows BMP image
@@ -5969,7 +6115,7 @@ static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
// so let's treat all 15 and 16bit TGAs as RGB with no alpha.
}
-static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, unsigned int *palette_buffer, int palette_buffer_len, stbi__result_info *ri)
{
// read in the TGA header stuff
int tga_offset = stbi__get8(s);
@@ -6049,10 +6195,18 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
// any data to skip? (offset u
(Patch may be truncated, please check the link at the top of this post.)