From 7224b4040776a4f6fa51905771d2c438e65d5ca7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga 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 cbc822d843..934c1addff 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 62c1186246..f5fd6ca932 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 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 #include // ptrdiff_t on osx #include @@ -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 // 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 @@ -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