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
This commit is contained in:
Sam Lantinga 2025-02-22 12:22:44 -08:00
parent 945da099ae
commit 7224b40407
2 changed files with 226 additions and 73 deletions

View File

@ -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) {

View File

@ -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 usually = 0)
stbi__skip(s, tga_palette_start );
// load the palette
tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
if (!tga_palette) {
STBI_FREE(tga_data);
return stbi__errpuc("outofmem", "Out of memory");
if (palette_buffer) {
if (palette_buffer_len < tga_palette_len * tga_comp) {
STBI_FREE(tga_data);
return stbi__errpuc("buffer too small", "Palette buffer too small");
}
tga_palette = (unsigned char*)(void*)palette_buffer;
} else {
tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
if (!tga_palette) {
STBI_FREE(tga_data);
return stbi__errpuc("outofmem", "Out of memory");
}
}
if (tga_rgb16) {
stbi_uc *pal_entry = tga_palette;
@ -6063,7 +6217,8 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
}
} else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
STBI_FREE(tga_data);
STBI_FREE(tga_palette);
if (!palette_buffer)
STBI_FREE(tga_palette);
return stbi__errpuc("bad palette", "Corrupt TGA");
}
}
@ -6092,7 +6247,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
if ( read_next_pixel )
{
// load however much data we did have
if ( tga_indexed )
if ( tga_indexed && !palette_buffer )
{
// read in index, then perform the lookup
int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
@ -6142,7 +6297,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
}
}
// clear my palette, if I had one
if ( tga_palette != NULL )
if ( tga_palette != NULL && !palette_buffer )
{
STBI_FREE( tga_palette );
}
@ -6629,7 +6784,7 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c
if (!stbi__pic_load_core(s,x,y,comp, result)) {
STBI_FREE(result);
result=0;
return 0;
}
*px = x;
*py = y;
@ -7730,7 +7885,7 @@ static int stbi__pnm_is16(stbi__context *s)
}
#endif
#ifndef STB_INTERNAL_SDL
#if 0 /* not used in SDL */
static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
{
#ifndef STBI_NO_JPEG
@ -7772,9 +7927,7 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
#endif
return stbi__err("unknown image type", "Image not of any known type, or corrupt");
}
#endif // !STB_INTERNAL_SDL
#ifndef STB_INTERNAL_SDL
static int stbi__is_16_main(stbi__context *s)
{
#ifndef STBI_NO_PNG
@ -7790,7 +7943,7 @@ static int stbi__is_16_main(stbi__context *s)
#endif
return 0;
}
#endif // !STB_INTERNAL_SDL
#endif /**/
#ifndef STBI_NO_STDIO
STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)
@ -7836,7 +7989,7 @@ STBIDEF int stbi_is_16_bit_from_file(FILE *f)
}
#endif // !STBI_NO_STDIO
#ifndef STB_INTERNAL_SDL
#if 0 /* not used in SDL */
STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)
{
stbi__context s;
@ -7864,7 +8017,7 @@ STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user
stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
return stbi__is_16_main(&s);
}
#endif // !STB_INTERNAL_SDL
#endif /**/
#endif // STB_IMAGE_IMPLEMENTATION