diff --git a/8f9bb9563980b41e7695148b63bf09f7abd38a41.patch b/8f9bb9563980b41e7695148b63bf09f7abd38a41.patch new file mode 100644 index 0000000..fc8e60c --- /dev/null +++ b/8f9bb9563980b41e7695148b63bf09f7abd38a41.patch @@ -0,0 +1,3464 @@ +From 8f9bb9563980b41e7695148b63bf09f7abd38a41 Mon Sep 17 00:00:00 2001 +From: gitamohr +Date: Fri, 17 Sep 2021 23:28:16 -0700 +Subject: [PATCH] hio: Update stb_image code to latest versions, enable UTF-8 + filename support for Windows. + +See #1580 + +(Internal change: 2188891) +--- + pxr/imaging/hio/stb/README | 10 +- + pxr/imaging/hio/stb/stb_image.h | 887 ++++++++++++++++------ + pxr/imaging/hio/stb/stb_image.patch | 31 +- + pxr/imaging/hio/stb/stb_image_resize.h | 119 +-- + pxr/imaging/hio/stb/stb_image_write.h | 440 +++++++---- + pxr/imaging/hio/stb/stb_image_write.patch | 15 - + pxr/imaging/hio/stbImage.cpp | 6 + + 7 files changed, 1052 insertions(+), 456 deletions(-) + delete mode 100644 pxr/imaging/hio/stb/stb_image_write.patch + +diff --git a/pxr/imaging/hio/stb/README b/pxr/imaging/hio/stb/README +index 8b81ebcaea..8d2f1263a0 100644 +--- a/pxr/imaging/hio/stb/README ++++ b/pxr/imaging/hio/stb/README +@@ -1,9 +1,11 @@ + stb_image_write + +-Current version : 1.09 ++Current version : see file source versions in each .h file. + Source: https://github.com/nothings/stb + + Patch file: +-- Download original source code from github +-- diff -ruN stb_image_write.h > stb_image_write.patch +-- diff -ruN stb_image.h > stb_image.patch ++- Download original/new source code from github. ++- Inspect current .patch file to understand local modifications. ++- Merge existing code with new code to incorporate patches. ++- Generate new patch: ++ diff -ruN stb_image.h > stb_image.patch +diff --git a/pxr/imaging/hio/stb/stb_image.h b/pxr/imaging/hio/stb/stb_image.h +index 4c2d313b5b..03ccd13da5 100644 +--- a/pxr/imaging/hio/stb/stb_image.h ++++ b/pxr/imaging/hio/stb/stb_image.h +@@ -1,4 +1,4 @@ +-/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb ++/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: +@@ -48,6 +48,14 @@ LICENSE + + RECENT REVISION HISTORY: + ++ 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes ++ 2.26 (2020-07-13) many minor fixes ++ 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.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings +@@ -82,25 +90,37 @@ RECENT REVISION HISTORY: + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) +- Arseny Kapoulkine ++ Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen ++ Carmelo J Fdez-Aguera + + Bug & warning fixes +- Marc LeBlanc David Woo Guillaume George Martins Mozeiko +- Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan +- Dave Moore Roy Eltham Hayaki Saito Nathan Reed +- Won Chun Luke Graham Johan Duparc Nick Verigakis +- the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh +- Janez Zemva John Bartholomew Michal Cichon github:romigrou +- Jonathan Blow Ken Hamada Tero Hanninen github:svdijk +- Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar +- Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex +- Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 +- Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw +- Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus +- Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo +- Christian Floisand Kevin Schmidt github:darealshinji +- Blazej Dariusz Roszkowski github:Michaelangel007 ++ Marc LeBlanc David Woo Guillaume George Martins Mozeiko ++ Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski ++ Phil Jordan Dave Moore Roy Eltham ++ Hayaki Saito Nathan Reed Won Chun ++ Luke Graham Johan Duparc Nick Verigakis the Horde3D community ++ Thomas Ruf Ronny Chevalier github:rlyeh ++ Janez Zemva John Bartholomew Michal Cichon github:romigrou ++ Jonathan Blow Ken Hamada Tero Hanninen github:svdijk ++ Eugene Golushkov Laurent Gomila Cort Stratton github:snagar ++ Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex ++ Cass Everitt Ryamond Barbiero github:grim210 ++ Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw ++ Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus ++ Josh Tobin Matthew Gregan github:poppolopoppo ++ Julian Raschke Gregory Mullen Christian Floisand github:darealshinji ++ Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 ++ Brad Weinberger Matvey Cherevko github:mosra ++ Luca Sas Alexander Veselov Zack Middleton [reserved] ++ Ryan C. Gordon [reserved] [reserved] ++ DO NOT ADD YOUR NAME HERE ++ ++ Jacko Dirks ++ ++ To add your name to the credits, pick a random blank space in the middle and fill it. ++ 80% of merge conflicts on stb PRs are due to people adding their name at the end ++ of the credits. + */ + + #ifndef STBI_INCLUDE_STB_IMAGE_H +@@ -159,6 +179,42 @@ RECENT REVISION HISTORY: + // + // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. + // ++// To query the width, height and component count of an image without having to ++// decode the full file, you can use the stbi_info family of functions: ++// ++// int x,y,n,ok; ++// ok = stbi_info(filename, &x, &y, &n); ++// // returns ok=1 and sets x, y, n if image is a supported format, ++// // 0 otherwise. ++// ++// Note that stb_image pervasively uses ints in its public API for sizes, ++// including sizes of memory buffers. This is now part of the API and thus ++// hard to change without causing breakage. As a result, the various image ++// loaders all have certain limits on image size; these differ somewhat ++// by format but generally boil down to either just under 2GB or just under ++// 1GB. When the decoded image would be larger than this, stb_image decoding ++// will fail. ++// ++// Additionally, stb_image will reject image files that have any of their ++// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, ++// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, ++// the only way to have an image with such dimensions load correctly ++// is for it to have a rather extreme aspect ratio. Either way, the ++// assumption here is that such larger images are likely to be malformed ++// or malicious. If you do need to load an image with individual dimensions ++// larger than that, and it still fits in the overall size limit, you can ++// #define STBI_MAX_DIMENSIONS on your own to be something larger. ++// ++// =========================================================================== ++// ++// 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 +@@ -171,12 +227,12 @@ RECENT REVISION HISTORY: + // + // 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 +-// 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, + // 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 +-// make more explicit reasons why performance can't be emphasized. ++// provide more explicit reasons why performance can't be emphasized. + // + // - Portable ("ease of use") + // - Small source code footprint ("easy to maintain") +@@ -219,11 +275,10 @@ RECENT REVISION HISTORY: + // + // HDR image support (disable by defining STBI_NO_HDR) + // +-// stb_image now supports loading HDR images in general, and currently +-// the Radiance .HDR file format, although the support is provided +-// generically. You can still load any file through the existing interface; +-// if you attempt to load an HDR file, it will be automatically remapped to +-// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; ++// stb_image supports loading HDR images in general, and currently the Radiance ++// .HDR file format specifically. You can still load any file through the existing ++// interface; if you attempt to load an HDR file, it will be automatically remapped ++// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; + // both of these constants can be reconfigured through this interface: + // + // stbi_hdr_to_ldr_gamma(2.2f); +@@ -255,11 +310,10 @@ RECENT REVISION HISTORY: + // + // iPhone PNG support: + // +-// By default we convert iphone-formatted PNGs back to RGB, even though +-// they are internally encoded differently. You can disable this conversion +-// by by calling stbi_convert_iphone_png_to_rgb(0), in which case +-// you will always just get the native iphone "format" through (which +-// is BGR stored in RGB). ++// We optionally support converting iPhone-formatted PNGs (which store ++// premultiplied BGRA) back to RGB, even though they're internally encoded ++// differently. To enable this conversion, call ++// stbi_convert_iphone_png_to_rgb(1). + // + // Call stbi_set_unpremultiply_on_load(1) as well to force a divide per + // pixel to remove any premultiplied alpha *only* if the image file explicitly +@@ -301,7 +355,14 @@ RECENT REVISION HISTORY: + // - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still + // want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB + // +- ++// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater ++// than that size (in either width or height) without further processing. ++// This is to let programs in the wild set an upper bound to prevent ++// denial-of-service attacks on untrusted data, as one could generate a ++// valid image of gigantic dimensions and force stb_image to allocate a ++// huge block of memory and spend disproportionate time decoding it. By ++// default this is set to (1 << 24), which is 16777216, but that's still ++// very big. + + #ifndef STBI_NO_STDIO + #include +@@ -319,6 +380,7 @@ enum + STBI_rgb_alpha = 4 + }; + ++#include + typedef unsigned char stbi_uc; + typedef unsigned short stbi_us; + +@@ -326,11 +388,13 @@ typedef unsigned short stbi_us; + extern "C" { + #endif + ++#ifndef STBIDEF + #ifdef STB_IMAGE_STATIC + #define STBIDEF static + #else + #define STBIDEF extern + #endif ++#endif + + ////////////////////////////////////////////////////////////////////////////// + // +@@ -355,10 +419,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_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 + STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +@@ -366,6 +426,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 + #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 +@@ -413,7 +481,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f); + + + // 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); + + // free the loaded image -- this is just free() +@@ -446,6 +514,13 @@ 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); + ++// 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_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); ++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); ++ + // 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); +@@ -525,6 +600,12 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch + #define STBI_ASSERT(x) assert(x) + #endif + ++#ifdef __cplusplus ++#define STBI_EXTERN extern "C" ++#else ++#define STBI_EXTERN extern ++#endif ++ + + #ifndef _MSC_VER + #ifdef __cplusplus +@@ -536,6 +617,23 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch + #define stbi_inline __forceinline + #endif + ++#ifndef STBI_NO_THREAD_LOCALS ++ #if defined(__cplusplus) && __cplusplus >= 201103L ++ #define STBI_THREAD_LOCAL thread_local ++ #elif defined(__GNUC__) && __GNUC__ < 5 ++ #define STBI_THREAD_LOCAL __thread ++ #elif defined(_MSC_VER) ++ #define STBI_THREAD_LOCAL __declspec(thread) ++ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) ++ #define STBI_THREAD_LOCAL _Thread_local ++ #endif ++ ++ #ifndef STBI_THREAD_LOCAL ++ #if defined(__GNUC__) ++ #define STBI_THREAD_LOCAL __thread ++ #endif ++ #endif ++#endif + + #ifdef _MSC_VER + typedef unsigned short stbi__uint16; +@@ -566,7 +664,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + #ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) + #else +- #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) ++ #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) + #endif + + #if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +@@ -649,14 +747,18 @@ static int stbi__cpuid3(void) + + #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) + { + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; + } ++#endif ++ + #else // assume GCC-style if not VC++ + #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) + { + // If we're even attempting to compile this on GCC/Clang, that means +@@ -664,6 +766,8 @@ static int stbi__sse2_available(void) + // instructions at will, and so are we. + return 1; + } ++#endif ++ + #endif + #endif + +@@ -674,14 +778,21 @@ static int stbi__sse2_available(void) + + #ifdef STBI_NEON + #include +-// assume GCC or Clang on ARM targets ++#ifdef _MSC_VER ++#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name ++#else + #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + #endif ++#endif + + #ifndef STBI_SIMD_ALIGN + #define STBI_SIMD_ALIGN(type, name) type name + #endif + ++#ifndef STBI_MAX_DIMENSIONS ++#define STBI_MAX_DIMENSIONS (1 << 24) ++#endif ++ + /////////////////////////////////////////////// + // + // stbi__context struct and start_xxx functions +@@ -699,6 +810,7 @@ typedef struct + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; ++ int callback_already_read; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +@@ -712,6 +824,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) + { + s->io.read = NULL; + s->read_from_callbacks = 0; ++ s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; + } +@@ -723,7 +836,8 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void * + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; +- s->img_buffer_original = s->buffer_start; ++ s->callback_already_read = 0; ++ s->img_buffer = s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; + } +@@ -737,12 +851,17 @@ static int stbi__stdio_read(void *user, char *data, int size) + + static void stbi__stdio_skip(void *user, int n) + { ++ int ch; + fseek((FILE*) user, n, SEEK_CUR); ++ ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ ++ if (ch != EOF) { ++ ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ ++ } + } + + static int stbi__stdio_eof(void *user) + { +- return feof((FILE*) user); ++ return feof((FILE*) user) || ferror((FILE *) user); + } + + static stbi_io_callbacks stbi__stdio_callbacks = +@@ -838,21 +957,27 @@ static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); + static int stbi__pnm_test(stbi__context *s); + static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); + static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); ++static int stbi__pnm_is16(stbi__context *s); + #endif + +-// this is not threadsafe +-static const char *stbi__g_failure_reason; ++static ++#ifdef STBI_THREAD_LOCAL ++STBI_THREAD_LOCAL ++#endif ++const char *stbi__g_failure_reason; + + 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 + + static void *stbi__malloc(size_t size) + { +@@ -891,11 +1016,13 @@ static int stbi__mul2sizes_valid(int a, int 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 + static int stbi__mad2sizes_valid(int a, int b, int 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 + static int stbi__mad3sizes_valid(int a, int b, int c, int add) +@@ -905,7 +1032,7 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add) + } + + // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +-#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) ++#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) + static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) + { + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && +@@ -913,12 +1040,14 @@ static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) + } + #endif + ++#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) + // mallocs with size overflow checking + static void *stbi__malloc_mad2(int a, int b, int add) + { + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); + } ++#endif + + static void *stbi__malloc_mad3(int a, int b, int c, int add) + { +@@ -926,7 +1055,7 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add) + return stbi__malloc(a*b*c + add); + } + +-#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) ++#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) + static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) + { + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; +@@ -962,13 +1091,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); + #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) + { +- 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) + { + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields +@@ -976,9 +1121,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + +- #ifndef STBI_NO_JPEG +- if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); +- #endif ++ // 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); + #endif +@@ -990,10 +1134,19 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); ++ #else ++ STBI_NOTUSED(bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif ++ ++ // then the formats that can end up attempting to load with just 1 or 2 ++ // 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, ri); ++ #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif +@@ -1070,6 +1223,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) + { + int slice; +@@ -1077,10 +1231,11 @@ static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int byt + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { +- stbi__vertical_flip(bytes, w, h, bytes_per_pixel); +- bytes += slice_size; ++ stbi__vertical_flip(bytes, w, h, bytes_per_pixel); ++ bytes += slice_size; + } + } ++#endif + + static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) + { +@@ -1090,8 +1245,10 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, + if (result == NULL) + return NULL; + ++ // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. ++ STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); ++ + if (ri.bits_per_channel != 8) { +- STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } +@@ -1114,8 +1271,10 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, + if (result == NULL) + return NULL; + ++ // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. ++ STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); ++ + if (ri.bits_per_channel != 16) { +- STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } +@@ -1131,7 +1290,7 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, + 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) + { + if (stbi__vertically_flip_on_load && result != NULL) { +@@ -1143,10 +1302,38 @@ static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, in + + #ifndef STBI_NO_STDIO + ++#if defined(_WIN32) && 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(_WIN32) && 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) + { + FILE *f; ++#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) ++ wchar_t wMode[64]; ++ wchar_t wFilename[1024]; ++ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) ++ return 0; ++ ++ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) ++ return 0; ++ + #if defined(_MSC_VER) && _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)) + f=0; + #else +@@ -1237,15 +1424,15 @@ STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *u + 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) + { + unsigned char *result; +- stbi__context s; +- stbi__start_mem(&s,buffer,len); +- ++ stbi__context s; ++ stbi__start_mem(&s,buffer,len); ++ + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { +- stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); ++ stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + +- return result; ++ return result; + } + #endif + +@@ -1390,6 +1577,7 @@ enum + static void stbi__refill_buffer(stbi__context *s) + { + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); ++ s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file +@@ -1414,6 +1602,9 @@ stbi_inline static stbi_uc stbi__get8(stbi__context *s) + 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) + { + if (s->io.read) { +@@ -1425,9 +1616,14 @@ stbi_inline static int stbi__at_eof(stbi__context *s) + + 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) + { ++ if (n == 0) return; // already there! + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; +@@ -1442,7 +1638,11 @@ static void stbi__skip(stbi__context *s, int 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) + { + if (s->io.read) { +@@ -1466,18 +1666,27 @@ static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) + } else + 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) + { + int z = 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) + { + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); + } ++#endif + + #if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) + // nothing +@@ -1493,13 +1702,16 @@ static int stbi__get16le(stbi__context *s) + static stbi__uint32 stbi__get32le(stbi__context *s) + { + stbi__uint32 z = stbi__get16le(s); +- return z + (stbi__get16le(s) << 16); ++ z += (stbi__uint32)stbi__get16le(s) << 16; ++ return z; + } + #endif + + #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 +@@ -1515,7 +1727,11 @@ static stbi_uc stbi__compute_y(int r, int g, int b) + { + 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) + { + int i,j; +@@ -1539,19 +1755,19 @@ 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; + // avoid switch per pixel, so use switch per scanline and massive macros + 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,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,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(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } 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,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,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; +- default: STBI_ASSERT(0); ++ 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; ++ default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } +@@ -1559,12 +1775,20 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r + STBI_FREE(data); + 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) + { + 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) + { + int i,j; +@@ -1588,19 +1812,19 @@ 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; + // avoid switch per pixel, so use switch per scanline and massive macros + 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,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,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(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } 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,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,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; +- default: STBI_ASSERT(0); ++ 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; ++ default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } +@@ -1608,6 +1832,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r + STBI_FREE(data); + return good; + } ++#endif + + #ifndef STBI_NO_LINEAR + static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +@@ -1623,7 +1848,11 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) + for (k=0; k < n; ++k) { + 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); + return output; +@@ -1902,13 +2131,12 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) + int sgn; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + +- sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB ++ sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) + k = stbi_lrot(j->code_buffer, n); +- STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; +- return k + (stbi__jbias[n] & ~sgn); ++ return k + (stbi__jbias[n] & (sgn - 1)); + } + + // get some unsigned bits +@@ -1958,7 +2186,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); +- if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); ++ if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); +@@ -2015,11 +2243,12 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__ + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); ++ if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; +- data[0] = (short) (dc << j->succ_low); ++ data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) +@@ -2056,7 +2285,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__ + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; +- data[zig] = (short) ((r >> 8) << shift); ++ data[zig] = (short) ((r >> 8) * (1 << shift)); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); +@@ -2074,7 +2303,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__ + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; +- data[zig] = (short) (stbi__extend_receive(j,s) << shift); ++ data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); +@@ -3005,6 +3234,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires ++ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); ++ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; +@@ -3036,6 +3267,13 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + ++ // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios ++ // and I've never seen a non-corrupted JPEG file actually use them ++ for (i=0; i < s->img_n; ++i) { ++ if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); ++ if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); ++ } ++ + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; +@@ -3591,12 +3829,16 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp + else + decode_n = z->s->img_n; + ++ // nothing to do if no components requested; check this now to avoid ++ // accessing uninitialized coutput[0] later ++ if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } ++ + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; +- stbi_uc *coutput[4]; ++ stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + +@@ -3717,7 +3959,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + 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; } + } + } + } +@@ -3733,6 +3975,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re + { + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); ++ if (!j) return stbi__errpuc("outofmem", "Out of memory"); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); +@@ -3745,6 +3988,7 @@ static int stbi__jpeg_test(stbi__context *s) + { + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); ++ if (!j) return stbi__err("outofmem", "Out of memory"); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); +@@ -3769,6 +4013,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) + { + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); ++ if (!j) return stbi__err("outofmem", "Out of memory"); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); +@@ -3788,6 +4033,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) + // fast-way is faster to check than jpeg huffman, but slow way is slower + #define STBI__ZFAST_BITS 9 // accelerate all cases in default tables + #define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) ++#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet + + // zlib-style huffman encoding + // (jpegs packs from left, zlib from right, so can't share code) +@@ -3797,8 +4043,8 @@ typedef struct + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; +- stbi_uc size[288]; +- stbi__uint16 value[288]; ++ stbi_uc size[STBI__ZNSYMS]; ++ stbi__uint16 value[STBI__ZNSYMS]; + } stbi__zhuffman; + + stbi_inline static int stbi__bitreverse16(int n) +@@ -3885,16 +4131,23 @@ typedef struct + stbi__zhuffman z_length, z_distance; + } stbi__zbuf; + ++stbi_inline static int stbi__zeof(stbi__zbuf *z) ++{ ++ return (z->zbuffer >= z->zbuffer_end); ++} ++ + stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) + { +- if (z->zbuffer >= z->zbuffer_end) return 0; +- return *z->zbuffer++; ++ return stbi__zeof(z) ? 0 : *z->zbuffer++; + } + + static void stbi__fill_bits(stbi__zbuf *z) + { + do { +- STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); ++ if (z->code_buffer >= (1U << z->num_bits)) { ++ z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ ++ return; ++ } + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +@@ -3919,10 +4172,11 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; +- if (s == 16) return -1; // invalid code! ++ if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; +- STBI_ASSERT(z->size[b] == s); ++ if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! ++ if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +@@ -3931,7 +4185,12 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) + stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) + { + int b,s; +- if (a->num_bits < 16) stbi__fill_bits(a); ++ if (a->num_bits < 16) { ++ if (stbi__zeof(a)) { ++ return -1; /* report error for unexpected end of data. */ ++ } ++ stbi__fill_bits(a); ++ } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; +@@ -3945,13 +4204,16 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) + static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes + { + char *q; +- int cur, limit, old_limit; ++ unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); +- cur = (int) (z->zout - z->zout_start); +- limit = old_limit = (int) (z->zout_end - z->zout_start); +- while (cur + n > limit) ++ cur = (unsigned int) (z->zout - z->zout_start); ++ limit = old_limit = (unsigned) (z->zout_end - z->zout_start); ++ if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); ++ while (cur + n > limit) { ++ if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); + limit *= 2; ++ } + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); +@@ -4049,11 +4311,12 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; +- } else if (c == 17) ++ } else if (c == 17) { + c = stbi__zreceive(a,3)+3; +- else { +- STBI_ASSERT(c == 18); ++ } else if (c == 18) { + c = stbi__zreceive(a,7)+11; ++ } else { ++ return stbi__err("bad codelengths", "Corrupt PNG"); + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); +@@ -4079,7 +4342,7 @@ static int stbi__parse_uncompressed_block(stbi__zbuf *a) + a->code_buffer >>= 8; + a->num_bits -= 8; + } +- STBI_ASSERT(a->num_bits == 0); ++ if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); +@@ -4101,6 +4364,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); ++ if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png +@@ -4108,7 +4372,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) + return 1; + } + +-static const stbi_uc stbi__zdefault_length[288] = ++static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = + { + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +@@ -4154,7 +4418,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) + } else { + if (type == 1) { + // use fixed code lengths +- if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; ++ if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; +@@ -4363,7 +4627,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { +- STBI_ASSERT(img_width_bytes <= x); ++ if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; +@@ -4551,6 +4815,7 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3 + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); ++ if (!final) return stbi__err("outofmem", "Out of memory"); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; +@@ -4671,19 +4936,46 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int + return 1; + } + +-static int stbi__unpremultiply_on_load = 0; +-static int stbi__de_iphone_flag = 0; ++static int stbi__unpremultiply_on_load_global = 0; ++static int stbi__de_iphone_flag_global = 0; + + STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) + { +- stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; ++ stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; + } + + STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) + { +- stbi__de_iphone_flag = flag_true_if_should_convert; ++ stbi__de_iphone_flag_global = flag_true_if_should_convert; ++} ++ ++#ifndef STBI_THREAD_LOCAL ++#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global ++#define stbi__de_iphone_flag stbi__de_iphone_flag_global ++#else ++static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; ++static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; ++ ++STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) ++{ ++ stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; ++ stbi__unpremultiply_on_load_set = 1; + } + ++STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) ++{ ++ stbi__de_iphone_flag_local = flag_true_if_should_convert; ++ stbi__de_iphone_flag_set = 1; ++} ++ ++#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ ++ ? stbi__unpremultiply_on_load_local \ ++ : stbi__unpremultiply_on_load_global) ++#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ ++ ? stbi__de_iphone_flag_local \ ++ : stbi__de_iphone_flag_global) ++#endif // STBI_THREAD_LOCAL ++ + static void stbi__de_iphone(stbi__png *z) + { + stbi__context *s = z->s; +@@ -4732,7 +5024,7 @@ static void stbi__de_iphone(stbi__png *z) + static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) + { + 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__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; +@@ -4758,8 +5050,10 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); +- s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); +- s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); ++ s->img_x = stbi__get32be(s); ++ s->img_y = stbi__get32be(s); ++ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); ++ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); +@@ -4883,6 +5177,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; ++ // end of PNG chunk, read and skip CRC ++ stbi__get32be(s); + return 1; + } + +@@ -4913,10 +5209,12 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st + 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 (p->depth < 8) ++ if (p->depth <= 8) + ri->bits_per_channel = 8; ++ else if (p->depth == 16) ++ ri->bits_per_channel = 16; + else +- ri->bits_per_channel = p->depth; ++ return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { +@@ -5018,11 +5316,11 @@ static int stbi__high_bit(unsigned int z) + { + int n=0; + if (z == 0) return -1; +- if (z >= 0x10000) n += 16, z >>= 16; +- if (z >= 0x00100) n += 8, z >>= 8; +- if (z >= 0x00010) n += 4, z >>= 4; +- if (z >= 0x00004) n += 2, z >>= 2; +- if (z >= 0x00002) n += 1, z >>= 1; ++ if (z >= 0x10000) { n += 16; z >>= 16; } ++ if (z >= 0x00100) { n += 8; z >>= 8; } ++ if (z >= 0x00010) { n += 4; z >>= 4; } ++ if (z >= 0x00004) { n += 2; z >>= 2; } ++ if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; + } + +@@ -5039,7 +5337,7 @@ static int stbi__bitcount(unsigned int a) + // extract an arbitrarily-aligned N-bit value (N=bits) + // from v, and then make it 8-bits long and fractionally + // 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] = { + 0, +@@ -5053,7 +5351,7 @@ static int stbi__shiftsigned(int v, int shift, int bits) + v <<= -shift; + else + v >>= shift; +- STBI_ASSERT(v >= 0 && v < 256); ++ STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +@@ -5063,8 +5361,35 @@ typedef struct + { + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; ++ int extra_read; + } stbi__bmp_data; + ++static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) ++{ ++ // BI_BITFIELDS specifies masks explicitly, don't override ++ if (compress == 3) ++ return 1; ++ ++ if (compress == 0) { ++ if (info->bpp == 16) { ++ info->mr = 31u << 10; ++ info->mg = 31u << 5; ++ info->mb = 31u << 0; ++ } else if (info->bpp == 32) { ++ info->mr = 0xffu << 16; ++ info->mg = 0xffu << 8; ++ info->mb = 0xffu << 0; ++ info->ma = 0xffu << 24; ++ info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 ++ } else { ++ // otherwise, use defaults, which is all-0 ++ info->mr = info->mg = info->mb = info->ma = 0; ++ } ++ return 1; ++ } ++ return 0; // error ++} ++ + static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) + { + int hsz; +@@ -5075,6 +5400,9 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; ++ info->extra_read = 14; ++ ++ if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { +@@ -5089,6 +5417,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); ++ if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes ++ if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres +@@ -5103,21 +5433,12 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { +- if (info->bpp == 32) { +- info->mr = 0xffu << 16; +- info->mg = 0xffu << 8; +- info->mb = 0xffu << 0; +- info->ma = 0xffu << 24; +- info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 +- } else { +- info->mr = 31u << 10; +- info->mg = 31u << 5; +- info->mb = 31u << 0; +- } ++ stbi__bmp_set_mask_defaults(info, compress); + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); ++ info->extra_read += 12; + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? +@@ -5127,6 +5448,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { ++ // V4/V5 header + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); +@@ -5134,6 +5456,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); ++ if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs ++ stbi__bmp_set_mask_defaults(info, compress); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters +@@ -5166,6 +5490,9 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + ++ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ + mr = info.mr; + mg = info.mg; + mb = info.mb; +@@ -5174,13 +5501,21 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req + + if (info.hsz == 12) { + if (info.bpp < 24) +- psize = (info.offset - 14 - 24) / 3; ++ psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) +- psize = (info.offset - 14 - info.hsz) >> 2; ++ psize = (info.offset - info.extra_read - info.hsz) >> 2; ++ } ++ if (psize == 0) { ++ if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) { ++ return stbi__errpuc("bad offset", "Corrupt BMP"); ++ } + } + +- s->img_n = ma ? 4 : 3; ++ if (info.bpp == 24 && ma == 0xff000000) ++ s->img_n = 3; ++ else ++ s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else +@@ -5202,7 +5537,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req + if (info.hsz != 12) stbi__get8(s); + 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; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; +@@ -5216,6 +5551,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][1]; + out[z++] = pal[color][2]; ++ if (target == 4) out[z++] = 255; ++ if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); +@@ -5249,7 +5586,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 z = 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; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; +@@ -5267,6 +5604,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); ++ if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { +@@ -5308,7 +5646,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 *p2 = out + (s->img_y-1-j)*s->img_x*target; + 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; + } + } + } +@@ -5488,6 +5826,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); ++ STBI_NOTUSED(tga_x_origin); // @TODO ++ STBI_NOTUSED(tga_y_origin); // @TODO ++ ++ if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) +@@ -5528,6 +5871,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req + // do I need to load a palette? + if ( tga_indexed) + { ++ if (tga_palette_len == 0) { /* you have to have at least one entry! */ ++ STBI_FREE(tga_data); ++ return stbi__errpuc("bad palette", "Corrupt TGA"); ++ } ++ + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette +@@ -5651,6 +5999,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; ++ STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; + } +@@ -5735,6 +6084,9 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req + h = stbi__get32be(s); + w = stbi__get32be(s); + ++ if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) +@@ -5798,7 +6150,7 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req + // Else if n is 128, noop. + // 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. + stbi__skip(s, h * channelCount * 2 ); + +@@ -6089,6 +6441,10 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c + + x = stbi__get16be(s); + y = stbi__get16be(s); ++ ++ if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + +@@ -6098,6 +6454,7 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); ++ if (!result) return stbi__errpuc("outofmem", "Out of memory"); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { +@@ -6136,7 +6493,7 @@ typedef struct + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned +- stbi_uc *history; ++ stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; +@@ -6197,6 +6554,9 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in + g->ratio = stbi__get8(s); + g->transparent = -1; + ++ if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); ++ if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); ++ + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; +@@ -6210,6 +6570,7 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in + static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) + { + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); ++ if (!g) return stbi__err("outofmem", "Out of memory"); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); +@@ -6224,7 +6585,7 @@ static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) + static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) + { + stbi_uc *p, *c; +- int idx; ++ int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty +@@ -6233,12 +6594,12 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) + + if (g->cur_y >= g->max_y) return; + +- idx = g->cur_x + g->cur_y; ++ idx = g->cur_x + g->cur_y; + p = &g->out[idx]; +- g->history[idx / 4] = 1; ++ g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; +- if (c[3] > 128) { // don't render transparent pixels; ++ if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; +@@ -6347,31 +6708,36 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) + // two back is the image from two frames ago, used for a very specific disposal format + static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) + { +- int dispose; +- int first_frame; +- int pi; +- int pcount; ++ int dispose; ++ int first_frame; ++ int pi; ++ int pcount; ++ STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) +- first_frame = 0; ++ first_frame = 0; + if (g->out == 0) { +- 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); +- g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); +- g->history = (stbi_uc *) stbi__malloc(g->w * g->h); +- if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); +- +- // image is treated as "tranparent" at the start - ie, nothing overwrites the current background; ++ if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header ++ if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) ++ return stbi__errpuc("too large", "GIF image is too large"); ++ pcount = g->w * g->h; ++ 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 "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" +- // color refers to teh color that was there the previous frame. +- memset( g->out, 0x00, 4 * g->w * g->h ); +- memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent) +- memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame +- first_frame = 1; ++ // color refers to the color that was there the previous frame. ++ memset(g->out, 0x00, 4 * pcount); ++ memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) ++ memset(g->history, 0x00, pcount); // pixels that were affected previous frame ++ first_frame = 1; + } else { +- // second frame - how do we dispoase of the previous one? +- dispose = (g->eflags & 0x1C) >> 2; +- pcount = g->w * g->h; ++ // second frame - how do we dispose of the previous one? ++ dispose = (g->eflags & 0x1C) >> 2; ++ pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background +@@ -6380,32 +6746,32 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { +- memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); ++ memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } +- } else if (dispose == 2) { +- // restore what was changed last frame to background before that frame; ++ } else if (dispose == 2) { ++ // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { +- memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); ++ memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { +- // This is a non-disposal case eithe way, so just ++ // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + +- // background is what out is after the undoing of the previou frame; +- memcpy( g->background, g->out, 4 * g->w * g->h ); ++ // background is what out is after the undoing of the previou frame; ++ memcpy( g->background, g->out, 4 * g->w * g->h ); + } + +- // clear my history; ++ // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { +- int tag = stbi__get8(s); ++ int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { +@@ -6427,6 +6793,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_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); + + if (g->lflags & 0x40) { +@@ -6443,19 +6816,19 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else +- return stbi__errpuc("missing color table", "Corrupt GIF"); +- ++ return stbi__errpuc("missing color table", "Corrupt GIF"); ++ + o = stbi__process_gif_raster(s, g); +- if (o == NULL) return NULL; ++ if (!o) return NULL; + +- // if this was the first frame, +- pcount = g->w * g->h; ++ // if this was the first frame, ++ pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { +- g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; +- memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); ++ g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; ++ memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } +@@ -6466,7 +6839,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i + case 0x21: // Comment Extension. + { + int len; +- int ext = stbi__get8(s); ++ int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { +@@ -6475,23 +6848,23 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i + + // unset old transparent + if (g->transparent >= 0) { +- g->pal[g->transparent][3] = 255; +- } ++ g->pal[g->transparent][3] = 255; ++ } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { +- g->pal[g->transparent][3] = 0; ++ g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent +- stbi__skip(s, 1); +- g->transparent = -1; ++ stbi__skip(s, 1); ++ g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } +- } ++ } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } +@@ -6507,18 +6880,35 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i + } + } + ++static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) ++{ ++ STBI_FREE(g->out); ++ STBI_FREE(g->history); ++ STBI_FREE(g->background); ++ ++ if (out) STBI_FREE(out); ++ if (delays && *delays) STBI_FREE(*delays); ++ return stbi__errpuc("outofmem", "Out of memory"); ++} ++ + static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) + { + if (stbi__gif_test(s)) { +- int layers = 0; ++ int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; +- stbi_uc *two_back = 0; ++ stbi_uc *two_back = 0; + stbi__gif g; +- int stride; ++ int stride; ++ int out_size = 0; ++ int delays_size = 0; ++ ++ STBI_NOTUSED(out_size); ++ STBI_NOTUSED(delays_size); ++ + memset(&g, 0, sizeof(g)); + if (delays) { +- *delays = 0; ++ *delays = 0; + } + + do { +@@ -6528,44 +6918,61 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, + if (u) { + *x = g.w; + *y = g.h; +- ++layers; +- stride = g.w * g.h * 4; +- ++ ++layers; ++ stride = g.w * g.h * 4; ++ + if (out) { +- out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); ++ void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); ++ if (!tmp) ++ return stbi__load_gif_main_outofmem(&g, out, delays); ++ else { ++ out = (stbi_uc*) tmp; ++ out_size = layers * stride; ++ } ++ + if (delays) { +- *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); ++ int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); ++ if (!new_delays) ++ return stbi__load_gif_main_outofmem(&g, out, delays); ++ *delays = new_delays; ++ delays_size = layers * sizeof(int); + } + } else { +- out = (stbi_uc*)stbi__malloc( layers * stride ); ++ out = (stbi_uc*)stbi__malloc( layers * stride ); ++ if (!out) ++ return stbi__load_gif_main_outofmem(&g, out, delays); ++ out_size = layers * stride; + if (delays) { +- *delays = (int*) stbi__malloc( layers * sizeof(int) ); ++ *delays = (int*) stbi__malloc( layers * sizeof(int) ); ++ if (!*delays) ++ return stbi__load_gif_main_outofmem(&g, out, delays); ++ delays_size = layers * sizeof(int); + } + } +- memcpy( out + ((layers - 1) * stride), u, stride ); ++ memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { +- two_back = out - 2 * stride; ++ two_back = out - 2 * stride; + } + + if (delays) { +- (*delays)[layers - 1U] = g.delay; ++ (*delays)[layers - 1U] = g.delay; + } + } +- } while (u != 0); ++ } while (u != 0); + +- // free temp buffer; +- STBI_FREE(g.out); +- STBI_FREE(g.history); +- STBI_FREE(g.background); ++ // free temp buffer; ++ STBI_FREE(g.out); ++ STBI_FREE(g.history); ++ STBI_FREE(g.background); + +- // do the final conversion after loading everything; ++ // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + +- *z = layers; ++ *z = layers; + return out; + } else { +- return stbi__errpuc("not GIF", "Image was not as a gif type."); ++ return stbi__errpuc("not GIF", "Image was not as a gif type."); + } + } + +@@ -6574,6 +6981,7 @@ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); ++ STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker +@@ -6582,14 +6990,17 @@ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req + *y = g.h; + + // moved conversion to after successful load so that the same +- // can be done for multiple frames. ++ // can be done for multiple frames. + if (req_comp && req_comp != 4) + 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; + STBI_FREE(g.history); +- STBI_FREE(g.background); ++ STBI_FREE(g.background); + + return u; + } +@@ -6714,6 +7125,9 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re + token += 3; + width = (int) strtol(token, NULL, 10); + ++ if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); ++ if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); ++ + *x = width; + *y = height; + +@@ -6856,12 +7270,18 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); +- stbi__rewind( s ); +- if (p == NULL) ++ if (p == NULL) { ++ stbi__rewind( s ); + return 0; ++ } + if (x) *x = s->img_x; + 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; + } + #endif +@@ -6919,8 +7339,8 @@ static int stbi__psd_is16(stbi__context *s) + stbi__rewind( s ); + return 0; + } +- (void) stbi__get32be(s); +- (void) stbi__get32be(s); ++ STBI_NOTUSED(stbi__get32be(s)); ++ STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); +@@ -6999,7 +7419,6 @@ static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) + // Known limitations: + // Does not support comments in the header section + // Does not support ASCII image data (formats P2 and P3) +-// Does not support 16-bit-per-channel + + #ifndef STBI_NO_PNM + +@@ -7020,19 +7439,23 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req + stbi_uc *out; + STBI_NOTUSED(ri); + +- if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) ++ ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); ++ if (ri->bits_per_channel == 0) + return 0; + ++ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); ++ + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + +- if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) ++ if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) + return stbi__errpuc("too large", "PNM too large"); + +- out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); ++ out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); +- stbi__getn(s, out, s->img_n * s->img_x * s->img_y); ++ stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8)); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); +@@ -7108,11 +7531,19 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value +- +- if (maxv > 255) +- return stbi__err("max value > 255", "PPM image not 8-bit"); ++ if (maxv > 65535) ++ return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); ++ else if (maxv > 255) ++ return 16; + else +- return 1; ++ return 8; ++} ++ ++static int stbi__pnm_is16(stbi__context *s) ++{ ++ if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) ++ return 1; ++ return 0; + } + #endif + +@@ -7168,6 +7599,9 @@ static int stbi__is_16_main(stbi__context *s) + if (stbi__psd_is16(s)) return 1; + #endif + ++ #ifndef STBI_NO_PNM ++ if (stbi__pnm_is16(s)) return 1; ++ #endif + return 0; + } + +@@ -7247,6 +7681,7 @@ STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user + + /* + 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.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug +diff --git a/pxr/imaging/hio/stb/stb_image.patch b/pxr/imaging/hio/stb/stb_image.patch +index 868b0a74fb..22fc041cba 100644 +--- a/pxr/imaging/hio/stb/stb_image.patch ++++ b/pxr/imaging/hio/stb/stb_image.patch +@@ -1,6 +1,6 @@ +---- stb/stb_image.h 2018-11-20 14:06:26.446637000 -0800 +-+++ stb_image.h 2018-11-20 14:10:10.830961000 -0800 +-@@ -420,14 +420,14 @@ ++--- stb/stb_image.h 2021-09-16 11:52:38.284782000 -0700k +++++ stb_image.h 2021-09-16 13:45:48.159770000 -0700 ++@@ -488,14 +488,14 @@ + STBIDEF void stbi_image_free (void *retval_from_stbi_load); + + // get image dimensions & components without fully decoding +@@ -19,7 +19,7 @@ + STBIDEF int stbi_is_16_bit (char const *filename); + STBIDEF int stbi_is_16_bit_from_file(FILE *f); + #endif +-@@ -792,7 +792,7 @@ ++@@ -911,7 +911,7 @@ + #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); +@@ -28,7 +28,7 @@ + static int stbi__png_is16(stbi__context *s); + #endif + +-@@ -4290,6 +4290,7 @@ ++@@ -4554,6 +4554,7 @@ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +@@ -36,7 +36,16 @@ + } stbi__png; + + +-@@ -4818,6 +4819,13 @@ ++@@ -4955,7 +4956,7 @@ ++ static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; ++ static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; ++ ++-STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +++STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) ++ { ++ stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; ++ stbi__unpremultiply_on_load_set = 1; ++@@ -5112,6 +5113,13 @@ + break; + } + +@@ -50,7 +59,7 @@ + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); +-@@ -4945,7 +4994,7 @@ ++@@ -5243,7 +5251,7 @@ + return r; + } + +@@ -59,7 +68,7 @@ + { + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); +-@@ -4954,21 +5003,22 @@ ++@@ -5252,21 +5260,22 @@ + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; +@@ -85,7 +94,7 @@ + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); +-@@ -7107,14 +7157,14 @@ ++@@ -7538,14 +7547,14 @@ + } + #endif + +@@ -102,7 +111,7 @@ + #endif + + #ifndef STBI_NO_GIF +-@@ -7163,23 +7213,23 @@ ++@@ -7597,23 +7606,23 @@ + } + + #ifndef STBI_NO_STDIO +@@ -130,7 +139,7 @@ + fseek(f,pos,SEEK_SET); + return r; + } +-@@ -7206,18 +7256,18 @@ ++@@ -7640,18 +7649,18 @@ + } + #endif // !STBI_NO_STDIO + +diff --git a/pxr/imaging/hio/stb/stb_image_resize.h b/pxr/imaging/hio/stb/stb_image_resize.h +index 031ca99dc3..ef9e6fe870 100644 +--- a/pxr/imaging/hio/stb/stb_image_resize.h ++++ b/pxr/imaging/hio/stb/stb_image_resize.h +@@ -1,4 +1,4 @@ +-/* stb_image_resize - v0.95 - public domain image resizing ++/* stb_image_resize - v0.97 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + +@@ -20,8 +20,8 @@ + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( +- input_pixels , in_w , in_h , 0, +- output_pixels, out_w, out_h, 0, ++ input_pixels , in_w , in_h , 0, ++ output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + +@@ -159,6 +159,8 @@ + Nathan Reed: warning fixes + + REVISIONS ++ 0.97 (2020-02-02) fixed warning ++ 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights +@@ -193,6 +195,7 @@ typedef uint16_t stbir_uint16; + typedef uint32_t stbir_uint32; + #endif + ++#ifndef STBIRDEF + #ifdef STB_IMAGE_RESIZE_STATIC + #define STBIRDEF static + #else +@@ -202,7 +205,7 @@ typedef uint32_t stbir_uint32; + #define STBIRDEF extern + #endif + #endif +- ++#endif + + ////////////////////////////////////////////////////////////////////////////// + // +@@ -231,7 +234,7 @@ STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , i + int num_channels); + + +-// The following functions interpret image data as gamma-corrected sRGB. ++// The following functions interpret image data as gamma-corrected sRGB. + // Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, + // or otherwise provide the index of the alpha channel. Flags value + // of 0 will probably do the right thing if you're not sure what +@@ -304,19 +307,19 @@ typedef enum + STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, ++ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, ++ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, ++ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + +@@ -348,7 +351,7 @@ STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, ++ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +@@ -356,7 +359,7 @@ STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, ++ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, +@@ -366,7 +369,7 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, ++ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +@@ -668,14 +671,14 @@ static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, + }; +- ++ + static stbir_uint8 stbir__linear_to_srgb_uchar(float in) + { + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; +- ++ + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. +@@ -683,13 +686,13 @@ static stbir_uint8 stbir__linear_to_srgb_uchar(float in) + in = minval.f; + if (in > almostone.f) + in = almostone.f; +- ++ + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; +- ++ + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +@@ -1061,7 +1064,11 @@ static void stbir__calculate_coefficients_upsample(stbir_filter filter, float sc + total_filter += coefficient_group[i]; + } + +- STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); ++ // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. ++ // It would be true in exact math but is at best approximately true in floating-point math, ++ // and it would not make sense to try and put actual bounds on this here because it depends ++ // on the image aspect ratio which can get pretty extreme. ++ //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. +@@ -1086,7 +1093,7 @@ static void stbir__calculate_coefficients_downsample(stbir_filter filter, float + { + int i; + +- STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. ++ STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; +@@ -1100,7 +1107,11 @@ static void stbir__calculate_coefficients_downsample(stbir_filter filter, float + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + +- STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); ++ // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. ++ // It would be true in exact math but is at best approximately true in floating-point math, ++ // and it would not make sense to try and put actual bounds on this here because it depends ++ // on the image aspect ratio which can get pretty extreme. ++ //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { +@@ -1236,7 +1247,7 @@ static float* stbir__get_decode_buffer(stbir__info* stbir_info) + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; + } + +-#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace)) ++#define STBIR__DECODE(type, colorspace) ((int)(type) * (STBIR_MAX_COLORSPACES) + (int)(colorspace)) + + static void stbir__decode_scanline(stbir__info* stbir_info, int n) + { +@@ -1549,7 +1560,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; +- STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } +@@ -1570,7 +1580,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; +- STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } +@@ -1592,7 +1601,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; +- STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; +@@ -1615,7 +1623,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; +- STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; +@@ -1640,7 +1647,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; +- STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } +@@ -2324,8 +2330,9 @@ static int stbir__resize_allocated(stbir__info *info, + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + +- if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) ++ if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); ++ } + + if (alpha_channel >= info->channels) + return 0; +@@ -2442,7 +2449,7 @@ static int stbir__resize_arbitrary( + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, +- output_data, output_stride_in_bytes, ++ output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); +@@ -2496,7 +2503,7 @@ STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels + STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, ++ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) + { + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, +@@ -2508,7 +2515,7 @@ STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int + STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, ++ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) + { + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, +@@ -2521,7 +2528,7 @@ STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int + STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, ++ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) + { + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, +@@ -2535,7 +2542,7 @@ STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, ++ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) + { +@@ -2550,7 +2557,7 @@ STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, ++ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, +@@ -2571,7 +2578,7 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, +- stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, ++ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +@@ -2590,38 +2597,38 @@ This software is available under 2 licenses -- choose whichever you prefer. + ------------------------------------------------------------------------------ + ALTERNATIVE A - MIT License + Copyright (c) 2017 Sean Barrett +-Permission is hereby granted, free of charge, to any person obtaining a copy of +-this software and associated documentation files (the "Software"), to deal in +-the Software without restriction, including without limitation the rights to +-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +-of the Software, and to permit persons to whom the Software is furnished to do ++Permission is hereby granted, free of charge, to any person obtaining a copy of ++this software and associated documentation files (the "Software"), to deal in ++the Software without restriction, including without limitation the rights to ++use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: +-The above copyright notice and this permission notice shall be included in all ++The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + ------------------------------------------------------------------------------ + ALTERNATIVE B - Public Domain (www.unlicense.org) + This is free and unencumbered software released into the public domain. +-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +-software, either in source code form or as a compiled binary, for any purpose, ++Anyone is free to copy, modify, publish, use, compile, sell, or distribute this ++software, either in source code form or as a compiled binary, for any purpose, + commercial or non-commercial, and by any means. +-In jurisdictions that recognize copyright laws, the author or authors of this +-software dedicate any and all copyright interest in the software to the public +-domain. We make this dedication for the benefit of the public at large and to +-the detriment of our heirs and successors. We intend this dedication to be an +-overt act of relinquishment in perpetuity of all present and future rights to ++In jurisdictions that recognize copyright laws, the author or authors of this ++software dedicate any and all copyright interest in the software to the public ++domain. We make this dedication for the benefit of the public at large and to ++the detriment of our heirs and successors. We intend this dedication to be an ++overt act of relinquishment in perpetuity of all present and future rights to + this software under copyright law. +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ------------------------------------------------------------------------------ + */ +diff --git a/pxr/imaging/hio/stb/stb_image_write.h b/pxr/imaging/hio/stb/stb_image_write.h +index 7c63a2dc20..e4b32ed1bc 100644 +--- a/pxr/imaging/hio/stb/stb_image_write.h ++++ b/pxr/imaging/hio/stb/stb_image_write.h +@@ -1,4 +1,4 @@ +-/* stb_image_write - v1.09 - public domain - http://nothings.org/stb/stb_image_write.h ++/* stb_image_write - v1.16 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + +@@ -10,15 +10,9 @@ + + Will probably not work correctly with strict-aliasing optimizations. + +- If using a modern Microsoft Compiler, non-safe versions of CRT calls may cause +- compilation warnings or even errors. To avoid this, also before #including, +- +- #define STBI_MSC_SECURE_CRT +- + ABOUT: + +- This header file is a library for writing images to C stdio. It could be +- adapted to write to memory or a general streaming interface; let me know. ++ This header file is a library for writing images to C stdio or a callback. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation; though providing a custom +@@ -38,6 +32,14 @@ + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + ++UNICODE: ++ ++ If compiling for Windows and you wish to use Unicode filenames, compile ++ with ++ #define STBIW_WINDOWS_UTF8 ++ and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert ++ Windows wchar_t filenames to utf8. ++ + USAGE: + + There are five functions, one for each image file format: +@@ -103,7 +105,7 @@ + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. +- ++ + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). +@@ -111,7 +113,7 @@ + CREDITS: + + +- Sean Barrett - PNG/BMP/TGA ++ Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements +@@ -138,6 +140,7 @@ + Ivan Tikhonov + github:ignotion + Adam Schackart ++ Andrew Kensler + + LICENSE + +@@ -148,6 +151,8 @@ LICENSE + #ifndef INCLUDE_STB_IMAGE_WRITE_H + #define INCLUDE_STB_IMAGE_WRITE_H + ++#include ++ + // if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' + #ifndef STBIWDEF + #ifdef STB_IMAGE_WRITE_STATIC +@@ -162,9 +167,9 @@ LICENSE + #endif + + #ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +-extern int stbi_write_tga_with_rle; +-extern int stbi_write_png_compression_level; +-extern int stbi_write_force_png_filter; ++STBIWDEF int stbi_write_tga_with_rle; ++STBIWDEF int stbi_write_png_compression_level; ++STBIWDEF int stbi_write_force_png_filter; + #endif + + #ifndef STBI_WRITE_NO_STDIO +@@ -173,6 +178,10 @@ STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const + STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); ++ ++#ifdef STBIW_WINDOWS_UTF8 ++STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); ++#endif + #endif + + typedef void stbi_write_func(void *context, void *data, int size); +@@ -239,17 +248,17 @@ STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + + #ifdef STB_IMAGE_WRITE_STATIC +-static int stbi__flip_vertically_on_write=0; + static int stbi_write_png_compression_level = 8; + static int stbi_write_tga_with_rle = 1; + static int stbi_write_force_png_filter = -1; + #else + int stbi_write_png_compression_level = 8; +-int stbi__flip_vertically_on_write=0; + int stbi_write_tga_with_rle = 1; + int stbi_write_force_png_filter = -1; + #endif + ++static int stbi__flip_vertically_on_write = 0; ++ + STBIWDEF void stbi_flip_vertically_on_write(int flag) + { + stbi__flip_vertically_on_write = flag; +@@ -259,6 +268,8 @@ typedef struct + { + stbi_write_func *func; + void *context; ++ unsigned char buffer[64]; ++ int buf_used; + } stbi__write_context; + + // initialize a callback-based context +@@ -275,15 +286,52 @@ static void stbi__stdio_write(void *context, void *data, int size) + fwrite(data,1,size,(FILE*) context); + } + +-static int stbi__start_write_file(stbi__write_context *s, const char *filename) ++#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) ++#ifdef __cplusplus ++#define STBIW_EXTERN extern "C" ++#else ++#define STBIW_EXTERN extern ++#endif ++STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); ++STBIW_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); ++ ++STBIWDEF int stbiw_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 *stbiw__fopen(char const *filename, char const *mode) + { + FILE *f; +-#ifdef STBI_MSC_SECURE_CRT +- if (fopen_s(&f, filename, "wb")) +- f = NULL; ++#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) ++ wchar_t wMode[64]; ++ wchar_t wFilename[1024]; ++ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) ++ return 0; ++ ++ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) ++ return 0; ++ ++#if defined(_MSC_VER) && _MSC_VER >= 1400 ++ if (0 != _wfopen_s(&f, wFilename, wMode)) ++ f = 0; + #else +- f = fopen(filename, "wb"); ++ f = _wfopen(wFilename, wMode); + #endif ++ ++#elif defined(_MSC_VER) && _MSC_VER >= 1400 ++ if (0 != fopen_s(&f, filename, mode)) ++ f=0; ++#else ++ f = fopen(filename, mode); ++#endif ++ return f; ++} ++ ++static int stbi__start_write_file(stbi__write_context *s, const char *filename) ++{ ++ FILE *f = stbiw__fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; + } +@@ -335,16 +383,36 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) + va_end(v); + } + ++static void stbiw__write_flush(stbi__write_context *s) ++{ ++ if (s->buf_used) { ++ s->func(s->context, &s->buffer, s->buf_used); ++ s->buf_used = 0; ++ } ++} ++ + static void stbiw__putc(stbi__write_context *s, unsigned char c) + { + s->func(s->context, &c, 1); + } + ++static void stbiw__write1(stbi__write_context *s, unsigned char a) ++{ ++ if ((size_t)s->buf_used + 1 > sizeof(s->buffer)) ++ stbiw__write_flush(s); ++ s->buffer[s->buf_used++] = a; ++} ++ + static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) + { +- unsigned char arr[3]; +- arr[0] = a, arr[1] = b, arr[2] = c; +- s->func(s->context, arr, 3); ++ int n; ++ if ((size_t)s->buf_used + 3 > sizeof(s->buffer)) ++ stbiw__write_flush(s); ++ n = s->buf_used; ++ s->buf_used = n+3; ++ s->buffer[n+0] = a; ++ s->buffer[n+1] = b; ++ s->buffer[n+2] = c; + } + + static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +@@ -353,7 +421,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in + int k; + + if (write_alpha < 0) +- s->func(s->context, &d[comp - 1], 1); ++ stbiw__write1(s, d[comp - 1]); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case +@@ -361,7 +429,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else +- s->func(s->context, d, 1); // monochrome TGA ++ stbiw__write1(s, d[0]); // monochrome TGA + break; + case 4: + if (!write_alpha) { +@@ -377,7 +445,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in + break; + } + if (write_alpha > 0) +- s->func(s->context, &d[comp - 1], 1); ++ stbiw__write1(s, d[comp - 1]); + } + + static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +@@ -391,16 +459,18 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i + if (stbi__flip_vertically_on_write) + vdir *= -1; + +- if (vdir < 0) +- j_end = -1, j = y-1; +- else +- j_end = y, j = 0; ++ if (vdir < 0) { ++ j_end = -1; j = y-1; ++ } else { ++ j_end = y; j = 0; ++ } + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } ++ stbiw__write_flush(s); + s->func(s->context, &zero, scanline_pad); + } + } +@@ -421,16 +491,27 @@ static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, + + static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) + { +- int pad = (-x*3) & 3; +- return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, +- "11 4 22 4" "4 44 22 444444", +- 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header +- 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header ++ if (comp != 4) { ++ // write RGB bitmap ++ int pad = (-x*3) & 3; ++ return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, ++ "11 4 22 4" "4 44 22 444444", ++ 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header ++ 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header ++ } else { ++ // RGBA bitmaps need a v4 header ++ // use BI_BITFIELDS mode with 32bpp and alpha mask ++ // (straight BI_RGB with alpha mask doesn't work in most readers) ++ return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0, ++ "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444", ++ 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header ++ 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header ++ } + } + + STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); + } +@@ -438,7 +519,7 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, + #ifndef STBI_WRITE_NO_STDIO + STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); +@@ -511,24 +592,25 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); +- s->func(s->context, &header, 1); ++ stbiw__write1(s, header); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); +- s->func(s->context, &header, 1); ++ stbiw__write1(s, header); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } ++ stbiw__write_flush(s); + } + return 1; + } + + STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); + } +@@ -536,7 +618,7 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, + #ifndef STBI_WRITE_NO_STDIO + STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); +@@ -552,7 +634,9 @@ STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const + + #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +-void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) ++#ifndef STBI_WRITE_NO_STDIO ++ ++static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) + { + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); +@@ -569,7 +653,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) + } + } + +-void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) ++static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) + { + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); +@@ -577,7 +661,7 @@ void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char dat + s->func(s->context, &databyte, 1); + } + +-void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) ++static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) + { + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code +@@ -585,7 +669,7 @@ void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *d + s->func(s->context, data, length); + } + +-void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) ++static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) + { + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; +@@ -686,18 +770,14 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + +-#ifdef STBI_MSC_SECURE_CRT +- len = sprintf_s(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); ++#ifdef __STDC_LIB_EXT1__ ++ len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + #else + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + #endif + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) +- // XXX PIXAR: fix to the following call to stbiw__write_hdr_scanline +- // XXX Issue: Original included extra multiplication by x when computing +- // XXX starting position of scanline +- // XXX Fix : deleted extra x + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); + STBIW_FREE(scratch); + return 1; +@@ -706,15 +786,14 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f + + STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); + } + +-#ifndef STBI_WRITE_NO_STDIO + STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); +@@ -732,7 +811,7 @@ STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const + + #ifndef STBIW_ZLIB_COMPRESS + // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +-#define stbiw__sbraw(a) ((int *) (a) - 2) ++#define stbiw__sbraw(a) ((int *) (void *) (a) - 2) + #define stbiw__sbm(a) stbiw__sbraw(a)[0] + #define stbiw__sbn(a) stbiw__sbraw(a)[1] + +@@ -813,7 +892,7 @@ static unsigned int stbiw__zhash(unsigned char *data) + + #endif // STBIW_ZLIB_COMPRESS + +-unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) ++STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) + { + #ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that +@@ -826,7 +905,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; +- unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); ++ unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; +@@ -849,7 +928,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); +- if (d >= best) best=d,bestloc=hlist[j]; ++ if (d >= best) { best=d; bestloc=hlist[j]; } + } + } + // when hash table entry is too long, delete half the entries +@@ -902,14 +981,31 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + ++ // store uncompressed instead if compression was worse ++ if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) { ++ stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1 ++ for (j = 0; j < data_len;) { ++ int blocklen = data_len - j; ++ if (blocklen > 32767) blocklen = 32767; ++ stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression ++ stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN ++ stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8)); ++ stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN ++ stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8)); ++ memcpy(out+stbiw__sbn(out), data+j, blocklen); ++ stbiw__sbn(out) += blocklen; ++ j += blocklen; ++ } ++ } ++ + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { +- for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; +- s1 %= 65521, s2 %= 65521; ++ for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } ++ s1 %= 65521; s2 %= 65521; + j += blocklen; + blocklen = 5552; + } +@@ -927,6 +1023,9 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l + + static unsigned int stbiw__crc32(unsigned char *buffer, int len) + { ++#ifdef STBIW_CRC32 ++ return STBIW_CRC32(buffer, len); ++#else + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, +@@ -968,6 +1067,7 @@ static unsigned int stbiw__crc32(unsigned char *buffer, int len) + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; ++#endif + } + + #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +@@ -998,9 +1098,15 @@ static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; ++ ++ if (type==0) { ++ memcpy(line_buffer, z, width*n); ++ return; ++ } ++ ++ // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { +- case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; +@@ -1009,20 +1115,17 @@ static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int + case 6: line_buffer[i] = z[i]; break; + } + } +- for (i=n; i < width*n; ++i) { +- switch (type) { +- case 0: line_buffer[i] = z[i]; break; +- case 1: line_buffer[i] = z[i] - z[i-n]; break; +- case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; +- case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; +- case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; +- case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; +- case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; +- } ++ switch (type) { ++ case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; ++ case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; ++ case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; ++ case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; ++ case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; ++ case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + +-unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) ++STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) + { + int force_filter = stbi_write_force_png_filter; + int ctype[5] = { -1, 0, 4, 2, 6 }; +@@ -1044,11 +1147,11 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; +- stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, force_filter, line_buffer); ++ stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { +- stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, filter_type, line_buffer); ++ stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; +@@ -1061,7 +1164,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it +- stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, best_filter, line_buffer); ++ stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } +@@ -1113,14 +1216,10 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const + { + FILE *f; + int len; +- unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); ++ unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; +-#ifdef STBI_MSC_SECURE_CRT +- if (fopen_s(&f, filename, "wb")) +- f = NULL; +-#else +- f = fopen(filename, "wb"); +-#endif ++ ++ f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); +@@ -1132,7 +1231,7 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const + STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) + { + int len; +- unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); ++ unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); +@@ -1226,26 +1325,31 @@ static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + bits[0] = val & ((1< 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + +@@ -1394,7 +1499,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), +- 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; ++ 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); +@@ -1417,38 +1522,74 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; +- const unsigned char *imageData = (const unsigned char *)data; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; ++ const unsigned char *dataR = (const unsigned char *)data; ++ const unsigned char *dataG = dataR + ofsG; ++ const unsigned char *dataB = dataR + ofsB; + int x, y, pos; +- for(y = 0; y < height; y += 8) { +- for(x = 0; x < width; x += 8) { +- float YDU[64], UDU[64], VDU[64]; +- for(row = y, pos = 0; row < y+8; ++row) { +- for(col = x; col < x+8; ++col, ++pos) { +- int p = (stbi__flip_vertically_on_write ? height-1-row : row)*width*comp + col*comp; +- float r, g, b; +- if(row >= height) { +- p -= width*comp*(row+1 - height); ++ if(subsample) { ++ for(y = 0; y < height; y += 16) { ++ for(x = 0; x < width; x += 16) { ++ float Y[256], U[256], V[256]; ++ for(row = y, pos = 0; row < y+16; ++row) { ++ // row >= height => use last input row ++ int clamped_row = (row < height) ? row : height - 1; ++ int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; ++ for(col = x; col < x+16; ++col, ++pos) { ++ // if col >= width => use pixel from last input column ++ int p = base_p + ((col < width) ? col : (width-1))*comp; ++ float r = dataR[p], g = dataG[p], b = dataB[p]; ++ Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; ++ U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; ++ V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } +- if(col >= width) { +- p -= comp*(col+1 - width); ++ } ++ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); ++ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); ++ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); ++ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); ++ ++ // subsample U,V ++ { ++ float subU[64], subV[64]; ++ int yy, xx; ++ for(yy = 0, pos = 0; yy < 8; ++yy) { ++ for(xx = 0; xx < 8; ++xx, ++pos) { ++ int j = yy*32+xx*2; ++ subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f; ++ subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f; ++ } + } +- +- r = imageData[p+0]; +- g = imageData[p+ofsG]; +- b = imageData[p+ofsB]; +- YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128; +- UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b; +- VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b; ++ DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); ++ DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } ++ } ++ } else { ++ for(y = 0; y < height; y += 8) { ++ for(x = 0; x < width; x += 8) { ++ float Y[64], U[64], V[64]; ++ for(row = y, pos = 0; row < y+8; ++row) { ++ // row >= height => use last input row ++ int clamped_row = (row < height) ? row : height - 1; ++ int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; ++ for(col = x; col < x+8; ++col, ++pos) { ++ // if col >= width => use pixel from last input column ++ int p = base_p + ((col < width) ? col : (width-1))*comp; ++ float r = dataR[p], g = dataG[p], b = dataB[p]; ++ Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; ++ U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; ++ V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; ++ } ++ } + +- DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); +- DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); +- DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); ++ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT); ++ DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); ++ DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); ++ } + } + } + +@@ -1465,7 +1606,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in + + STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); + } +@@ -1474,7 +1615,7 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, + #ifndef STBI_WRITE_NO_STDIO + STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) + { +- stbi__write_context s; ++ stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); +@@ -1487,6 +1628,17 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const + #endif // STB_IMAGE_WRITE_IMPLEMENTATION + + /* Revision history ++ 1.16 (2021-07-11) ++ make Deflate code emit uncompressed blocks when it would otherwise expand ++ support writing BMPs with alpha channel ++ 1.15 (2020-07-13) unknown ++ 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels ++ 1.13 ++ 1.12 ++ 1.11 (2019-08-11) ++ ++ 1.10 (2019-02-07) ++ support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) +@@ -1517,7 +1669,7 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) +- add monochrome TGA output ++ add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) +@@ -1535,38 +1687,38 @@ This software is available under 2 licenses -- choose whichever you prefer. + ------------------------------------------------------------------------------ + ALTERNATIVE A - MIT License + Copyright (c) 2017 Sean Barrett +-Permission is hereby granted, free of charge, to any person obtaining a copy of +-this software and associated documentation files (the "Software"), to deal in +-the Software without restriction, including without limitation the rights to +-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +-of the Software, and to permit persons to whom the Software is furnished to do ++Permission is hereby granted, free of charge, to any person obtaining a copy of ++this software and associated documentation files (the "Software"), to deal in ++the Software without restriction, including without limitation the rights to ++use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: +-The above copyright notice and this permission notice shall be included in all ++The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + ------------------------------------------------------------------------------ + ALTERNATIVE B - Public Domain (www.unlicense.org) + This is free and unencumbered software released into the public domain. +-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +-software, either in source code form or as a compiled binary, for any purpose, ++Anyone is free to copy, modify, publish, use, compile, sell, or distribute this ++software, either in source code form or as a compiled binary, for any purpose, + commercial or non-commercial, and by any means. +-In jurisdictions that recognize copyright laws, the author or authors of this +-software dedicate any and all copyright interest in the software to the public +-domain. We make this dedication for the benefit of the public at large and to +-the detriment of our heirs and successors. We intend this dedication to be an +-overt act of relinquishment in perpetuity of all present and future rights to ++In jurisdictions that recognize copyright laws, the author or authors of this ++software dedicate any and all copyright interest in the software to the public ++domain. We make this dedication for the benefit of the public at large and to ++the detriment of our heirs and successors. We intend this dedication to be an ++overt act of relinquishment in perpetuity of all present and future rights to + this software under copyright law. +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ------------------------------------------------------------------------------ + */ +diff --git a/pxr/imaging/hio/stb/stb_image_write.patch b/pxr/imaging/hio/stb/stb_image_write.patch +deleted file mode 100644 +index 0df4340b11..0000000000 +--- a/pxr/imaging/hio/stb/stb_image_write.patch ++++ /dev/null +@@ -1,15 +0,0 @@ +---- stb/stb_image_write.h 2018-02-11 11:57:53.000000000 -0800 +-+++ stb_image_write.h 2018-06-11 14:01:49.258945863 -0700 +-@@ -694,7 +694,11 @@ +- s->func(s->context, buffer, len); +- +- for(i=0; i < y; i++) +-- stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)*x); +-+ // XXX PIXAR: fix to the following call to stbiw__write_hdr_scanline +-+ // XXX Issue: Original included extra multiplication by x when computing +-+ // XXX starting position of scanline +-+ // XXX Fix : deleted extra x +-+ stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); +- STBIW_FREE(scratch); +- return 1; +- } +diff --git a/pxr/imaging/hio/stbImage.cpp b/pxr/imaging/hio/stbImage.cpp +index 8ac15e5420..da9efb1a7e 100644 +--- a/pxr/imaging/hio/stbImage.cpp ++++ b/pxr/imaging/hio/stbImage.cpp +@@ -47,6 +47,9 @@ ARCH_PRAGMA_PUSH + ARCH_PRAGMA_UNUSED_FUNCTION + + #define STB_IMAGE_STATIC ++#ifdef ARCH_OS_WINDOWS ++#define STBI_WINDOWS_UTF8 ++#endif + #define STB_IMAGE_IMPLEMENTATION + #include "pxr/imaging/hio/stb/stb_image.h" + +@@ -55,6 +58,9 @@ ARCH_PRAGMA_UNUSED_FUNCTION + #include "pxr/imaging/hio/stb/stb_image_resize.h" + + #define STB_IMAGE_WRITE_STATIC ++#ifdef ARCH_OS_WINDOWS ++#define STBIW_WINDOWS_UTF8 ++#endif + #define STB_IMAGE_WRITE_IMPLEMENTATION + #include "pxr/imaging/hio/stb/stb_image_write.h" + diff --git a/usd.spec b/usd.spec index 858f14d..08ab29b 100644 --- a/usd.spec +++ b/usd.spec @@ -40,7 +40,7 @@ Summary: 3D VFX pipeline interchange file format # do not contribute their license terms to the built RPMs.) License: ASL 2.0 and BSD and MIT and (MIT or Unlicense) URL: http://www.openusd.org/ -Source0: https://github.com/PixarAnimationStudios/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz +Source0: https://github.com/PixarAnimationStudios/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz Source1: org.open%{name}.%{name}view.desktop # https://github.com/PixarAnimationStudios/USD/issues/1387 @@ -49,6 +49,17 @@ Patch1: %{srcname}-20.05-soversion.patch # https://github.com/PixarAnimationStudios/USD/issues/1591 Patch2: USD-21.08-OpenEXR3.patch +# Backport 8f9bb9563980b41e7695148b63bf09f7abd38a41 from dev branch: +# hio: Update stb_image code to latest versions, enable UTF-8 filename support +# for Windows +# +# This gives us Pixar-specific patches that we can apply to the Fedora-packaged +# stb libraries. These include patches for CVE-2021-42715 and CVE-2021-42716, +# not yet merged upstream. +# +# It also ensures that a fix for CVE-2021-28021 (RHBZ#2015229) is present. +Patch3: https://github.com/PixarAnimationStudios/USD/commit/8f9bb9563980b41e7695148b63bf09f7abd38a41.patch + # Base BuildRequires: boost-devel BuildRequires: boost-program-options @@ -102,6 +113,12 @@ BuildRequires: hdf5-devel %endif # Header-only library: -static is for tracking per guidelines +# stb_image 2.27-0.7 is the minimum EVR to contain fixes for all of +# CVE-2021-28021, CVE-2021-42715, and CVE-2021-42716. +BuildRequires: stb_image-devel >= 2.27-0.7 +BuildRequires: stb_image-static +BuildRequires: stb_image_write-devel +BuildRequires: stb_image_write-static BuildRequires: stb_image_resize-devel BuildRequires: stb_image_resize-static @@ -131,13 +148,6 @@ Provides: bundled(SPIRV-Reflect) = 1.0 # Version from: pxr/imaging/hgiVulkan/vk_mem_alloc.h (header comment) Provides: bundled(VulkanMemoryAllocator) = 3.0.0~development -# Both of these are packaged in Fedora, but USD uses patched versions, so they -# must be bundled. -# Version from: pxr/imaging/hio/stb/stb_image.h -Provides: bundled(stb_image) = 2.19 -# Version from: pxr/imaging/hio/stb/stb_image_write.h -Provides: bundled(stb_image_write) = 1.09 - # This package is only available for x86_64 and aarch64 # Will fail to build on other architectures # https://bugzilla.redhat.com/show_bug.cgi?id=1960848 @@ -222,8 +232,12 @@ ln -s %{_datadir}/fonts/google-roboto pxr/usdImaging/usdviewq/fonts/Roboto ln -s %{_datadir}/fonts/google-roboto-mono \ pxr/usdImaging/usdviewq/fonts/Roboto_Mono -# Unbundle stb_image_resize: -ln -svf %{_includedir}/stb_image_resize.h pxr/imaging/hio/stb/ +# Unbundle stb_image, stb_image_write, stb_image_resize: +pushd pxr/imaging/hio/stb +cp -p %{_includedir}/stb_image.h %{_includedir}/stb_image_write.h . +cat stb_image.patch stb_image_write.patch | patch -p1 +ln -svf %{_includedir}/stb_image_resize.h ./ +popd # Use c++17 standard otherwise build fails sed -i 's|set(CMAKE_CXX_STANDARD 14)|set(CMAKE_CXX_STANDARD 17)|g' \