Update stb_image headers to latest version.

We are going to remove our libpng for stb_image.
This commit is contained in:
Edênis Freindorfer Azevedo 2020-02-29 20:26:39 -03:00 committed by Rafael Kitover
parent 3ca35d9ca6
commit 4da422d02b
2 changed files with 1996 additions and 136 deletions

View File

@ -1,4 +1,4 @@
/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb /* stb_image - v2.25 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@ -48,6 +48,12 @@ LICENSE
RECENT REVISION HISTORY: RECENT REVISION HISTORY:
2.25 (2020-02-02) fix warnings
2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
2.23 (2019-08-11) fix clang static analysis warning
2.22 (2019-03-04) gif fixes, fix warnings
2.21 (2019-02-25) fix typo in comment
2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs
2.19 (2018-02-11) fix warning 2.19 (2018-02-11) fix warning
2.18 (2018-01-30) fix warnings 2.18 (2018-01-30) fix warnings
2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
@ -84,6 +90,7 @@ RECENT REVISION HISTORY:
Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query)
Arseny Kapoulkine Arseny Kapoulkine
John-Mark Allen John-Mark Allen
Carmelo J Fdez-Aguera
Bug & warning fixes Bug & warning fixes
Marc LeBlanc David Woo Guillaume George Martins Mozeiko Marc LeBlanc David Woo Guillaume George Martins Mozeiko
@ -99,8 +106,9 @@ RECENT REVISION HISTORY:
Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
Christian Floisand Kevin Schmidt github:darealshinji Christian Floisand Kevin Schmidt JR Smith github:darealshinji
Blazej Dariusz Roszkowski github:Michaelangel007 Brad Weinberger Matvey Cherevko github:Michaelangel007
Blazej Dariusz Roszkowski Alexander Veselov
*/ */
#ifndef STBI_INCLUDE_STB_IMAGE_H #ifndef STBI_INCLUDE_STB_IMAGE_H
@ -161,6 +169,16 @@ RECENT REVISION HISTORY:
// //
// =========================================================================== // ===========================================================================
// //
// UNICODE:
//
// If compiling for Windows and you wish to use Unicode filenames, compile
// with
// #define STBI_WINDOWS_UTF8
// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert
// Windows wchar_t filenames to utf8.
//
// ===========================================================================
//
// Philosophy // Philosophy
// //
// stb libraries are designed with the following priorities: // stb libraries are designed with the following priorities:
@ -171,12 +189,12 @@ RECENT REVISION HISTORY:
// //
// Sometimes I let "good performance" creep up in priority over "easy to maintain", // Sometimes I let "good performance" creep up in priority over "easy to maintain",
// and for best performance I may provide less-easy-to-use APIs that give higher // and for best performance I may provide less-easy-to-use APIs that give higher
// performance, in addition to the easy to use ones. Nevertheless, it's important // performance, in addition to the easy-to-use ones. Nevertheless, it's important
// to keep in mind that from the standpoint of you, a client of this library, // to keep in mind that from the standpoint of you, a client of this library,
// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. // all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.
// //
// Some secondary priorities arise directly from the first two, some of which // Some secondary priorities arise directly from the first two, some of which
// make more explicit reasons why performance can't be emphasized. // provide more explicit reasons why performance can't be emphasized.
// //
// - Portable ("ease of use") // - Portable ("ease of use")
// - Small source code footprint ("easy to maintain") // - Small source code footprint ("easy to maintain")
@ -219,11 +237,10 @@ RECENT REVISION HISTORY:
// //
// HDR image support (disable by defining STBI_NO_HDR) // HDR image support (disable by defining STBI_NO_HDR)
// //
// stb_image now supports loading HDR images in general, and currently // stb_image supports loading HDR images in general, and currently the Radiance
// the Radiance .HDR file format, although the support is provided // .HDR file format specifically. You can still load any file through the existing
// generically. You can still load any file through the existing interface; // interface; if you attempt to load an HDR file, it will be automatically remapped
// if you attempt to load an HDR file, it will be automatically remapped to // to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
// both of these constants can be reconfigured through this interface: // both of these constants can be reconfigured through this interface:
// //
// stbi_hdr_to_ldr_gamma(2.2f); // stbi_hdr_to_ldr_gamma(2.2f);
@ -257,7 +274,7 @@ RECENT REVISION HISTORY:
// //
// By default we convert iphone-formatted PNGs back to RGB, even though // By default we convert iphone-formatted PNGs back to RGB, even though
// they are internally encoded differently. You can disable this conversion // they are internally encoded differently. You can disable this conversion
// by by calling stbi_convert_iphone_png_to_rgb(0), in which case // by calling stbi_convert_iphone_png_to_rgb(0), in which case
// you will always just get the native iphone "format" through (which // you will always just get the native iphone "format" through (which
// is BGR stored in RGB). // is BGR stored in RGB).
// //
@ -319,6 +336,7 @@ enum
STBI_rgb_alpha = 4 STBI_rgb_alpha = 4
}; };
#include <stdlib.h>
typedef unsigned char stbi_uc; typedef unsigned char stbi_uc;
typedef unsigned short stbi_us; typedef unsigned short stbi_us;
@ -326,11 +344,13 @@ typedef unsigned short stbi_us;
extern "C" { extern "C" {
#endif #endif
#ifndef STBIDEF
#ifdef STB_IMAGE_STATIC #ifdef STB_IMAGE_STATIC
#define STBIDEF static #define STBIDEF static
#else #else
#define STBIDEF extern #define STBIDEF extern
#endif #endif
#endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -355,10 +375,6 @@ 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); STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
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); 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);
#ifndef STBI_NO_GIF
STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
#endif
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
@ -366,6 +382,14 @@ STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in
// for stbi_load_from_file, file pointer is left pointing immediately after image // for stbi_load_from_file, file pointer is left pointing immediately after image
#endif #endif
#ifndef STBI_NO_GIF
STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
#endif
#ifdef STBI_WINDOWS_UTF8
STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
#endif
//////////////////////////////////// ////////////////////////////////////
// //
// 16-bits-per-channel interface // 16-bits-per-channel interface
@ -413,7 +437,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f);
// get a VERY brief reason for failure // get a VERY brief reason for failure
// NOT THREADSAFE // on most compilers (and ALL modern mainstream compilers) this is threadsafe
STBIDEF const char *stbi_failure_reason (void); STBIDEF const char *stbi_failure_reason (void);
// free the loaded image -- this is just free() // free the loaded image -- this is just free()
@ -446,6 +470,11 @@ 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 // 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); STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
// 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
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
// ZLIB client - used by PNG, available for other purposes // ZLIB client - used by PNG, available for other purposes
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
@ -525,6 +554,12 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#define STBI_ASSERT(x) assert(x) #define STBI_ASSERT(x) assert(x)
#endif #endif
#ifdef __cplusplus
#define STBI_EXTERN extern "C"
#else
#define STBI_EXTERN extern
#endif
#ifndef _MSC_VER #ifndef _MSC_VER
#ifdef __cplusplus #ifdef __cplusplus
@ -536,6 +571,17 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#define stbi_inline __forceinline #define stbi_inline __forceinline
#endif #endif
#ifndef STBI_NO_THREAD_LOCALS
#if defined(__cplusplus) && __cplusplus >= 201103L
#define STBI_THREAD_LOCAL thread_local
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define STBI_THREAD_LOCAL _Thread_local
#elif defined(__GNUC__)
#define STBI_THREAD_LOCAL __thread
#elif defined(_MSC_VER)
#define STBI_THREAD_LOCAL __declspec(thread)
#endif
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
typedef unsigned short stbi__uint16; typedef unsigned short stbi__uint16;
@ -649,14 +695,18 @@ static int stbi__cpuid3(void)
#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name #define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
static int stbi__sse2_available(void) static int stbi__sse2_available(void)
{ {
int info3 = stbi__cpuid3(); int info3 = stbi__cpuid3();
return ((info3 >> 26) & 1) != 0; return ((info3 >> 26) & 1) != 0;
} }
#endif
#else // assume GCC-style if not VC++ #else // assume GCC-style if not VC++
#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
static int stbi__sse2_available(void) static int stbi__sse2_available(void)
{ {
// If we're even attempting to compile this on GCC/Clang, that means // If we're even attempting to compile this on GCC/Clang, that means
@ -664,6 +714,8 @@ static int stbi__sse2_available(void)
// instructions at will, and so are we. // instructions at will, and so are we.
return 1; return 1;
} }
#endif
#endif #endif
#endif #endif
@ -840,19 +892,24 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int
static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
#endif #endif
// this is not threadsafe static
static const char *stbi__g_failure_reason; #ifdef STBI_THREAD_LOCAL
STBI_THREAD_LOCAL
#endif
const char *stbi__g_failure_reason;
STBIDEF const char *stbi_failure_reason(void) STBIDEF const char *stbi_failure_reason(void)
{ {
return stbi__g_failure_reason; return stbi__g_failure_reason;
} }
#ifndef STBI_NO_FAILURE_STRINGS
static int stbi__err(const char *str) static int stbi__err(const char *str)
{ {
stbi__g_failure_reason = str; stbi__g_failure_reason = str;
return 0; return 0;
} }
#endif
static void *stbi__malloc(size_t size) static void *stbi__malloc(size_t size)
{ {
@ -891,11 +948,13 @@ static int stbi__mul2sizes_valid(int a, int b)
return a <= INT_MAX/b; return a <= INT_MAX/b;
} }
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow // returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
static int stbi__mad2sizes_valid(int a, int b, int add) static int stbi__mad2sizes_valid(int a, int b, int add)
{ {
return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
} }
#endif
// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow // returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
static int stbi__mad3sizes_valid(int a, int b, int c, int add) static int stbi__mad3sizes_valid(int a, int b, int c, int add)
@ -913,12 +972,14 @@ static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
} }
#endif #endif
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// mallocs with size overflow checking // mallocs with size overflow checking
static void *stbi__malloc_mad2(int a, int b, int add) static void *stbi__malloc_mad2(int a, int b, int add)
{ {
if (!stbi__mad2sizes_valid(a, b, add)) return NULL; if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
return stbi__malloc(a*b + add); return stbi__malloc(a*b + add);
} }
#endif
static void *stbi__malloc_mad3(int a, int b, int c, int add) static void *stbi__malloc_mad3(int a, int b, int c, int add)
{ {
@ -962,13 +1023,29 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
#endif #endif
static int stbi__vertically_flip_on_load = 0; static int stbi__vertically_flip_on_load_global = 0;
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{ {
stbi__vertically_flip_on_load = flag_true_if_should_flip; stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
} }
#ifndef STBI_THREAD_LOCAL
#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global
#else
static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set;
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
stbi__vertically_flip_on_load_set = 1;
}
#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \
? stbi__vertically_flip_on_load_local \
: 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)
{ {
memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
@ -990,6 +1067,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
#endif #endif
#ifndef STBI_NO_PSD #ifndef STBI_NO_PSD
if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
#else
STBI_NOTUSED(bpc);
#endif #endif
#ifndef STBI_NO_PIC #ifndef STBI_NO_PIC
if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
@ -1070,6 +1149,7 @@ static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
} }
} }
#ifndef STBI_NO_GIF
static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)
{ {
int slice; int slice;
@ -1081,6 +1161,7 @@ static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int byt
bytes += slice_size; bytes += slice_size;
} }
} }
#endif
static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{ {
@ -1131,7 +1212,7 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
return (stbi__uint16 *) result; return (stbi__uint16 *) result;
} }
#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR) #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) static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
{ {
if (stbi__vertically_flip_on_load && result != NULL) { if (stbi__vertically_flip_on_load && result != NULL) {
@ -1143,10 +1224,38 @@ static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, in
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
#endif
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
{
return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
}
#endif
static FILE *stbi__fopen(char const *filename, char const *mode) static FILE *stbi__fopen(char const *filename, char const *mode)
{ {
FILE *f; FILE *f;
#if defined(_MSC_VER) && _MSC_VER >= 1400 #if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
wchar_t wMode[64];
wchar_t wFilename[1024];
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
return 0;
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
return 0;
#if _MSC_VER >= 1400
if (0 != _wfopen_s(&f, wFilename, wMode))
f = 0;
#else
f = _wfopen(wFilename, wMode);
#endif
#elif defined(_MSC_VER) && _MSC_VER >= 1400
if (0 != fopen_s(&f, filename, mode)) if (0 != fopen_s(&f, filename, mode))
f=0; f=0;
#else #else
@ -1414,6 +1523,9 @@ stbi_inline static stbi_uc stbi__get8(stbi__context *s)
return 0; return 0;
} }
#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
stbi_inline static int stbi__at_eof(stbi__context *s) stbi_inline static int stbi__at_eof(stbi__context *s)
{ {
if (s->io.read) { if (s->io.read) {
@ -1425,7 +1537,11 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
return s->img_buffer >= s->img_buffer_end; return s->img_buffer >= s->img_buffer_end;
} }
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)
// nothing
#else
static void stbi__skip(stbi__context *s, int n) static void stbi__skip(stbi__context *s, int n)
{ {
if (n < 0) { if (n < 0) {
@ -1442,7 +1558,11 @@ static void stbi__skip(stbi__context *s, int n)
} }
s->img_buffer += n; s->img_buffer += n;
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM)
// nothing
#else
static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
{ {
if (s->io.read) { if (s->io.read) {
@ -1466,18 +1586,27 @@ static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
} else } else
return 0; return 0;
} }
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static int stbi__get16be(stbi__context *s) static int stbi__get16be(stbi__context *s)
{ {
int z = stbi__get8(s); int z = stbi__get8(s);
return (z << 8) + stbi__get8(s); return (z << 8) + stbi__get8(s);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static stbi__uint32 stbi__get32be(stbi__context *s) static stbi__uint32 stbi__get32be(stbi__context *s)
{ {
stbi__uint32 z = stbi__get16be(s); stbi__uint32 z = stbi__get16be(s);
return (z << 16) + stbi__get16be(s); return (z << 16) + stbi__get16be(s);
} }
#endif
#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) #if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
// nothing // nothing
@ -1499,7 +1628,9 @@ static stbi__uint32 stbi__get32le(stbi__context *s)
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// generic converter from built-in img_n to req_comp // generic converter from built-in img_n to req_comp
@ -1515,7 +1646,11 @@ static stbi_uc stbi__compute_y(int r, int g, int b)
{ {
return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{ {
int i,j; int i,j;
@ -1539,18 +1674,18 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
// convert source image with img_n components to one with req_comp components; // convert source image with img_n components to one with req_comp components;
// avoid switch per pixel, so use switch per scanline and massive macros // avoid switch per pixel, so use switch per scanline and massive macros
switch (STBI__COMBO(img_n, req_comp)) { switch (STBI__COMBO(img_n, req_comp)) {
STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break; STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break;
STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break; STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break;
STBI__CASE(2,1) { dest[0]=src[0]; } break; STBI__CASE(2,1) { dest[0]=src[0]; } break;
STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break;
STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break; STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break;
STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break;
STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;
STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
default: STBI_ASSERT(0); default: STBI_ASSERT(0);
} }
#undef STBI__CASE #undef STBI__CASE
@ -1559,12 +1694,20 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
STBI_FREE(data); STBI_FREE(data);
return good; return good;
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 stbi__compute_y_16(int r, int g, int b) static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
{ {
return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{ {
int i,j; int i,j;
@ -1588,18 +1731,18 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
// convert source image with img_n components to one with req_comp components; // convert source image with img_n components to one with req_comp components;
// avoid switch per pixel, so use switch per scanline and massive macros // avoid switch per pixel, so use switch per scanline and massive macros
switch (STBI__COMBO(img_n, req_comp)) { switch (STBI__COMBO(img_n, req_comp)) {
STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break; STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break;
STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break; STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break;
STBI__CASE(2,1) { dest[0]=src[0]; } break; STBI__CASE(2,1) { dest[0]=src[0]; } break;
STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break;
STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break; STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break;
STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break;
STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;
STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
default: STBI_ASSERT(0); default: STBI_ASSERT(0);
} }
#undef STBI__CASE #undef STBI__CASE
@ -1608,6 +1751,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
STBI_FREE(data); STBI_FREE(data);
return good; return good;
} }
#endif
#ifndef STBI_NO_LINEAR #ifndef STBI_NO_LINEAR
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
@ -1623,7 +1767,11 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
for (k=0; k < n; ++k) { for (k=0; k < n; ++k) {
output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
} }
if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; }
if (n < comp) {
for (i=0; i < x*y; ++i) {
output[i*comp + n] = data[i*comp + n]/255.0f;
}
} }
STBI_FREE(data); STBI_FREE(data);
return output; return output;
@ -3596,7 +3744,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
int k; int k;
unsigned int i,j; unsigned int i,j;
stbi_uc *output; stbi_uc *output;
stbi_uc *coutput[4]; stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL };
stbi__resample res_comp[4]; stbi__resample res_comp[4];
@ -3717,7 +3865,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
if (n == 1) if (n == 1)
for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
else else
for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; }
} }
} }
} }
@ -4731,7 +4879,7 @@ static void stbi__de_iphone(stbi__png *z)
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)
{ {
stbi_uc palette[1024], pal_img_n=0; stbi_uc palette[1024], pal_img_n=0;
stbi_uc has_trans=0, tc[3]; stbi_uc has_trans=0, tc[3]={0};
stbi__uint16 tc16[3]; stbi__uint16 tc16[3];
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
int first=1,k,interlace=0, color=0, is_iphone=0; int first=1,k,interlace=0, color=0, is_iphone=0;
@ -4875,6 +5023,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
++s->img_n; ++s->img_n;
} }
STBI_FREE(z->expanded); z->expanded = NULL; STBI_FREE(z->expanded); z->expanded = NULL;
// end of PNG chunk, read and skip CRC
stbi__get32be(s);
return 1; return 1;
} }
@ -5009,11 +5159,11 @@ static int stbi__high_bit(unsigned int z)
{ {
int n=0; int n=0;
if (z == 0) return -1; if (z == 0) return -1;
if (z >= 0x10000) n += 16, z >>= 16; if (z >= 0x10000) { n += 16; z >>= 16; }
if (z >= 0x00100) n += 8, z >>= 8; if (z >= 0x00100) { n += 8; z >>= 8; }
if (z >= 0x00010) n += 4, z >>= 4; if (z >= 0x00010) { n += 4; z >>= 4; }
if (z >= 0x00004) n += 2, z >>= 2; if (z >= 0x00004) { n += 2; z >>= 2; }
if (z >= 0x00002) n += 1, z >>= 1; if (z >= 0x00002) { n += 1;/* >>= 1;*/ }
return n; return n;
} }
@ -5030,7 +5180,7 @@ static int stbi__bitcount(unsigned int a)
// extract an arbitrarily-aligned N-bit value (N=bits) // extract an arbitrarily-aligned N-bit value (N=bits)
// from v, and then make it 8-bits long and fractionally // from v, and then make it 8-bits long and fractionally
// extend it to full full range. // extend it to full full range.
static int stbi__shiftsigned(int v, int shift, int bits) static int stbi__shiftsigned(unsigned int v, int shift, int bits)
{ {
static unsigned int mul_table[9] = { static unsigned int mul_table[9] = {
0, 0,
@ -5044,7 +5194,7 @@ static int stbi__shiftsigned(int v, int shift, int bits)
v <<= -shift; v <<= -shift;
else else
v >>= shift; v >>= shift;
STBI_ASSERT(v >= 0 && v < 256); STBI_ASSERT(v < 256);
v >>= (8-bits); v >>= (8-bits);
STBI_ASSERT(bits >= 0 && bits <= 8); STBI_ASSERT(bits >= 0 && bits <= 8);
return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
@ -5054,6 +5204,7 @@ typedef struct
{ {
int bpp, offset, hsz; int bpp, offset, hsz;
unsigned int mr,mg,mb,ma, all_a; unsigned int mr,mg,mb,ma, all_a;
int extra_read;
} stbi__bmp_data; } stbi__bmp_data;
static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
@ -5066,6 +5217,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->offset = stbi__get32le(s); info->offset = stbi__get32le(s);
info->hsz = hsz = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s);
info->mr = info->mg = info->mb = info->ma = 0; info->mr = info->mg = info->mb = info->ma = 0;
info->extra_read = 14;
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
if (hsz == 12) { if (hsz == 12) {
@ -5109,6 +5261,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->mr = stbi__get32le(s); info->mr = stbi__get32le(s);
info->mg = stbi__get32le(s); info->mg = stbi__get32le(s);
info->mb = stbi__get32le(s); info->mb = stbi__get32le(s);
info->extra_read += 12;
// not documented, but generated by photoshop and handled by mspaint // not documented, but generated by photoshop and handled by mspaint
if (info->mr == info->mg && info->mg == info->mb) { if (info->mr == info->mg && info->mg == info->mb) {
// ?!?!? // ?!?!?
@ -5165,12 +5318,18 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz == 12) { if (info.hsz == 12) {
if (info.bpp < 24) if (info.bpp < 24)
psize = (info.offset - 14 - 24) / 3; psize = (info.offset - info.extra_read - 24) / 3;
} else { } else {
if (info.bpp < 16) if (info.bpp < 16)
psize = (info.offset - 14 - info.hsz) >> 2; psize = (info.offset - info.extra_read - info.hsz) >> 2;
}
if (psize == 0) {
STBI_ASSERT(info.offset == (s->img_buffer - s->buffer_start));
} }
if (info.bpp == 24 && ma == 0xff000000)
s->img_n = 3;
else
s->img_n = ma ? 4 : 3; s->img_n = ma ? 4 : 3;
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
target = req_comp; target = req_comp;
@ -5193,7 +5352,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz != 12) stbi__get8(s); if (info.hsz != 12) stbi__get8(s);
pal[i][3] = 255; pal[i][3] = 255;
} }
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
if (info.bpp == 1) width = (s->img_x + 7) >> 3; if (info.bpp == 1) width = (s->img_x + 7) >> 3;
else if (info.bpp == 4) width = (s->img_x + 1) >> 1; else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
else if (info.bpp == 8) width = s->img_x; else if (info.bpp == 8) width = s->img_x;
@ -5207,6 +5366,8 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
out[z++] = pal[color][0]; out[z++] = pal[color][0];
out[z++] = pal[color][1]; out[z++] = pal[color][1];
out[z++] = pal[color][2]; out[z++] = pal[color][2];
if (target == 4) out[z++] = 255;
if (i+1 == (int) s->img_x) break;
if((--bit_offset) < 0) { if((--bit_offset) < 0) {
bit_offset = 7; bit_offset = 7;
v = stbi__get8(s); v = stbi__get8(s);
@ -5240,7 +5401,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
int z = 0; int z = 0;
int easy=0; int easy=0;
stbi__skip(s, info.offset - 14 - info.hsz); stbi__skip(s, info.offset - info.extra_read - info.hsz);
if (info.bpp == 24) width = 3 * s->img_x; if (info.bpp == 24) width = 3 * s->img_x;
else if (info.bpp == 16) width = 2*s->img_x; else if (info.bpp == 16) width = 2*s->img_x;
else /* bpp = 32 and pad = 0 */ width=0; else /* bpp = 32 and pad = 0 */ width=0;
@ -5299,7 +5460,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
stbi_uc *p1 = out + j *s->img_x*target; stbi_uc *p1 = out + j *s->img_x*target;
stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;
for (i=0; i < (int) s->img_x*target; ++i) { for (i=0; i < (int) s->img_x*target; ++i) {
t = p1[i], p1[i] = p2[i], p2[i] = t; t = p1[i]; p1[i] = p2[i]; p2[i] = t;
} }
} }
} }
@ -5479,6 +5640,8 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
int RLE_repeating = 0; int RLE_repeating = 0;
int read_next_pixel = 1; int read_next_pixel = 1;
STBI_NOTUSED(ri); STBI_NOTUSED(ri);
STBI_NOTUSED(tga_x_origin); // @TODO
STBI_NOTUSED(tga_y_origin); // @TODO
// do a tiny bit of precessing // do a tiny bit of precessing
if ( tga_image_type >= 8 ) if ( tga_image_type >= 8 )
@ -5642,6 +5805,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
// Microsoft's C compilers happy... [8^( // Microsoft's C compilers happy... [8^(
tga_palette_start = tga_palette_len = tga_palette_bits = tga_palette_start = tga_palette_len = tga_palette_bits =
tga_x_origin = tga_y_origin = 0; tga_x_origin = tga_y_origin = 0;
STBI_NOTUSED(tga_palette_start);
// OK, done // OK, done
return tga_data; return tga_data;
} }
@ -5789,7 +5953,7 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req
// Else if n is 128, noop. // Else if n is 128, noop.
// Endloop // Endloop
// The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, // The RLE-compressed data is preceded by a 2-byte data count for each row in the data,
// which we're going to just skip. // which we're going to just skip.
stbi__skip(s, h * channelCount * 2 ); stbi__skip(s, h * channelCount * 2 );
@ -6342,22 +6506,27 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
int first_frame; int first_frame;
int pi; int pi;
int pcount; int pcount;
STBI_NOTUSED(req_comp);
// on first frame, any non-written pixels get the background colour (non-transparent) // on first frame, any non-written pixels get the background colour (non-transparent)
first_frame = 0; first_frame = 0;
if (g->out == 0) { if (g->out == 0) {
if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); if (!stbi__mad3sizes_valid(4, g->w, g->h, 0))
g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); return stbi__errpuc("too large", "GIF image is too large");
g->history = (stbi_uc *) stbi__malloc(g->w * g->h); pcount = g->w * g->h;
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); g->out = (stbi_uc *) stbi__malloc(4 * pcount);
g->background = (stbi_uc *) stbi__malloc(4 * pcount);
g->history = (stbi_uc *) stbi__malloc(pcount);
if (!g->out || !g->background || !g->history)
return stbi__errpuc("outofmem", "Out of memory");
// image is treated as "tranparent" at the start - ie, nothing overwrites the current background; // image is treated as "transparent" at the start - ie, nothing overwrites the current background;
// background colour is only used for pixels that are not rendered first frame, after that "background" // background colour is only used for pixels that are not rendered first frame, after that "background"
// color refers to teh color that was there the previous frame. // color refers to the color that was there the previous frame.
memset( g->out, 0x00, 4 * g->w * g->h ); memset(g->out, 0x00, 4 * pcount);
memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent) memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent)
memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame memset(g->history, 0x00, pcount); // pixels that were affected previous frame
first_frame = 1; first_frame = 1;
} else { } else {
// second frame - how do we dispoase of the previous one? // second frame - how do we dispoase of the previous one?
@ -6418,6 +6587,13 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
g->cur_x = g->start_x; g->cur_x = g->start_x;
g->cur_y = g->start_y; g->cur_y = g->start_y;
// if the width of the specified rectangle is 0, that means
// we may not see *any* pixels or the image is malformed;
// to make sure this is caught, move the current y down to
// max_y (which is what out_gif_code checks).
if (w == 0)
g->cur_y = g->max_y;
g->lflags = stbi__get8(s); g->lflags = stbi__get8(s);
if (g->lflags & 0x40) { if (g->lflags & 0x40) {
@ -6437,7 +6613,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
return stbi__errpuc("missing color table", "Corrupt GIF"); return stbi__errpuc("missing color table", "Corrupt GIF");
o = stbi__process_gif_raster(s, g); o = stbi__process_gif_raster(s, g);
if (o == NULL) return NULL; if (!o) return NULL;
// if this was the first frame, // if this was the first frame,
pcount = g->w * g->h; pcount = g->w * g->h;
@ -6523,7 +6699,15 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
stride = g.w * g.h * 4; stride = g.w * g.h * 4;
if (out) { if (out) {
out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); void *tmp = (stbi_uc*) STBI_REALLOC( out, layers * stride );
if (NULL == tmp) {
STBI_FREE(g.out);
STBI_FREE(g.history);
STBI_FREE(g.background);
return stbi__errpuc("outofmem", "Out of memory");
}
else
out = (stbi_uc*) tmp;
if (delays) { if (delays) {
*delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers );
} }
@ -6565,6 +6749,7 @@ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req
stbi_uc *u = 0; stbi_uc *u = 0;
stbi__gif g; stbi__gif g;
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
STBI_NOTUSED(ri);
u = stbi__gif_load_next(s, &g, comp, req_comp, 0); u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
@ -6576,6 +6761,9 @@ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req
// can be done for multiple frames. // can be done for multiple frames.
if (req_comp && req_comp != 4) if (req_comp && req_comp != 4)
u = stbi__convert_format(u, 4, req_comp, g.w, g.h); u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
} else if (g.out) {
// if there was an error and we allocated an image buffer, free it!
STBI_FREE(g.out);
} }
// free buffers needed for multiple frame loading; // free buffers needed for multiple frame loading;
@ -6852,7 +7040,12 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
return 0; return 0;
if (x) *x = s->img_x; if (x) *x = s->img_x;
if (y) *y = s->img_y; if (y) *y = s->img_y;
if (comp) *comp = info.ma ? 4 : 3; if (comp) {
if (info.bpp == 24 && info.ma == 0xff000000)
*comp = 3;
else
*comp = info.ma ? 4 : 3;
}
return 1; return 1;
} }
#endif #endif
@ -7238,6 +7431,7 @@ STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user
/* /*
revision history: revision history:
2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs
2.19 (2018-02-11) fix warning 2.19 (2018-02-11) fix warning
2.18 (2018-01-30) fix warnings 2.18 (2018-01-30) fix warnings
2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug

File diff suppressed because it is too large Load Diff