From 8b048b8d0a6cd8683b38368f2958f398e8cb5d01 Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 22:02:09 +0300 Subject: [PATCH 01/11] feat: add image I/O --- deps/stb_image.h | 7988 ++++++++++++++++++++++++++++++++++++++++ deps/stb_image_write.h | 1724 +++++++++ src/utils/image_io.c | 155 + src/utils/image_io.h | 14 + 4 files changed, 9881 insertions(+) create mode 100644 deps/stb_image.h create mode 100644 deps/stb_image_write.h create mode 100644 src/utils/image_io.c create mode 100644 src/utils/image_io.h diff --git a/deps/stb_image.h b/deps/stb_image.h new file mode 100644 index 0000000..9eedabe --- /dev/null +++ b/deps/stb_image.h @@ -0,0 +1,7988 @@ +/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.30 (2024-05-31) avoid erroneous gcc warning + 2.29 (2023-05-xx) optimizations + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff + 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 + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + 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 Neil Bickford 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 +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data); +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// 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 +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// 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 +// 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 +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// 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); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// 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 +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - 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 +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +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_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// 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 +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// on most compilers (and ALL modern mainstream compilers) this is threadsafe +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +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); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#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 + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #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 + +#if defined(_MSC_VER) || defined(__SYMBIAN32__) +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #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)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#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 + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +#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 + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + 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; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +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; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + 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; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +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) || ferror((FILE *) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +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 + +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) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*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) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, 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) || !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) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, 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) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#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; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +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_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 + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + 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; + + // 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 + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #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 + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + 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) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + 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) { + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + 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) { + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#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) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#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 + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#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) +{ + unsigned char *result; + 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 ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +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 + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + 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) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + 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; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + 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) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } 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 +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + 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 +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +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; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // 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,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(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(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(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_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + 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; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // 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,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(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(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(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_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + 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) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + 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 (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { + h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + + 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); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & (sgn - 1)); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + 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])); + + diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // 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; + + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + 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"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + 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; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + 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; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + j->marker = stbi__skip_jpeg_junk_at_end(j); + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); + } else { + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); + } + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + 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] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + 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; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +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"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +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"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// 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) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + int hit_zeof_once; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + 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) +{ + return stbi__zeof(z) ? 0 : *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + 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); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[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]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); + } + } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + 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"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } + return 1; + } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (len > a->zout_end - zout) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + } 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); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + 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); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(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 + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +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, + 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, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + a->hit_zeof_once = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + 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; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub +}; + +static int stbi__paeth(int a, int b, int c) +{ + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16 ? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + + for (j=0; j < y; ++j) { + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; + int filter = *raw++; + + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; + } + + raw += nk; + + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; + + // expand bits to bytes first + if (depth == 4) { + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; + } + } else if (depth == 2) { + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; + } + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; + } + } + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); + if (img_n == 1) { + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; + } + } else { + STBI_ASSERT(img_n == 3); + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; + } + } + } + } + } + + STBI_FREE(filter_buf); + if (!all_ok) return 0; + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // 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 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +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_global = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int 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; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + 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); + 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"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + } + // even with SCAN_header, have to scan to see if we have a tRNS + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } + if (z->depth == 16) { + for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning + tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n && k < 3; ++k) + tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + 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"); + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth <= 8) + ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; + else + 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) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +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;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// 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(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +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; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + 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) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + 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 + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 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) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + 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"); + info->mr = stbi__get32le(s); + 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 + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + 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; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); + } + } + + 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 + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + 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; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + 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); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + 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 - 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; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + 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) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + 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; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + 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 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // 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 + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // 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; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + 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) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // 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 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + 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"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // 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)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +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; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + 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; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +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 ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// 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; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + 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 + 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 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 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 + } + + 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 ); + } + } + } 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 ); + } + } + } else { + // 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 ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + 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) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // 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 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + 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; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +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; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + 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; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + 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) { + 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 ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; + if (delays) { + *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 ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // 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; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + 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 + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // 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; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + 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; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + if (p == NULL) { + stbi__rewind( s ); + return 0; + } + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + 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__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_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"); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } + + if (req_comp && req_comp != s->img_n) { + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + 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 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + 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 + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +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 +so, subject to the following conditions: +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 +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, +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 +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 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/deps/stb_image_write.h b/deps/stb_image_write.h new file mode 100644 index 0000000..e4b32ed --- /dev/null +++ b/deps/stb_image_write.h @@ -0,0 +1,1724 @@ +/* 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 + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + 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 + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + 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: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + 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). + +CREDITS: + + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + Andrew Kensler + +LICENSE + + See end of file for license information. + +*/ + +#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 +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif +#endif + +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +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 +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +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); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +#ifdef STB_IMAGE_WRITE_STATIC +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_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; +} + +typedef struct +{ + stbi_write_func *func; + void *context; + unsigned char buffer[64]; + int buf_used; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +#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; +#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 = _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; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + 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) +{ + 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) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + stbiw__write1(s, d[comp - 1]); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + stbiw__write1(s, d[0]); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + 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) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (stbi__flip_vertically_on_write) + vdir *= -1; + + 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); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + 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 = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#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 = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + int jend, jdir; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 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); + 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 = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#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 = { 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); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +#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])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +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); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +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 + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +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]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + 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 __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++) + 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; + } +} + +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 = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + 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); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +#ifndef STBIW_ZLIB_COMPRESS +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (void *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +#endif // STBIW_ZLIB_COMPRESS + +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 + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + 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]; } + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (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; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS +} + +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, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + 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) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) +{ + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + 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 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; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; 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; + } +} + +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 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int j,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + if (force_filter >= 5) { + force_filter = -1; + } + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + 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((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; + for (i = 0; i < x*n; ++i) { + est += abs((signed char) line_buffer[i]); + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + + f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +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((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k, subsample; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + subsample = quality <= 90 ? 1 : 0; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + 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,(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); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + 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; + 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; + } + } + 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; + } + } + 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, 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); + } + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +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 = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#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 = { 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); + return r; + } else + return 0; +} +#endif + +#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) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +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 +so, subject to the following conditions: +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 +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, +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 +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 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/src/utils/image_io.c b/src/utils/image_io.c new file mode 100644 index 0000000..c9530f4 --- /dev/null +++ b/src/utils/image_io.c @@ -0,0 +1,155 @@ +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include +#include + +#include "image_io.h" +#include "stb_image.h" +#include "stb_image_write.h" + +image_t *load_image(const char *filename) { + if (!filename) { + fprintf(stderr, "Error: NULL filename provided\n"); + return NULL; + } + + int width, height, channels; + unsigned char *image_data = + stbi_load(filename, &width, &height, &channels, 0); + if (!image_data) { + fprintf(stderr, "Error: Could not load image '%s': %s\n", filename, + stbi_failure_reason()); + return NULL; + } + + // Currently only RGB is supported + if (channels != 3) { + fprintf(stderr, "Error: unsupported number of channels (%d)\n", channels); + stbi_image_free(image_data); + return NULL; + } + + image_t *image = (image_t *)malloc(sizeof(image_t)); + if (!image) { + fprintf(stderr, "Error: memory allocation failed for image structure.\n"); + stbi_image_free(image_data); + return NULL; + } + + image->height = height; + image->width = width; + image->channels = channels; + image->image_data = image_data; + + return image; +} + +int store_image(const char *filename, image_t *image) { + if (!filename) { + fprintf(stderr, "Error: NULL filename provided\n"); + return -1; + } + + if (!image || !image->image_data) { + fprintf(stderr, "Error: NULL pointer in image\n"); + return -1; + } + + const char *dot = strrchr(filename, '.'); + if (!dot) { + fprintf(stderr, "Error: no file extension in '%s'\n", filename); + return -1; + } + + int result = 0; + const char *ext = dot + 1; + + if (strcmp(ext, "jpg") == 0 || strcmp(ext, "jpeg") == 0) { + result = stbi_write_jpg(filename, image->width, image->height, + image->channels, image->image_data, 95); + } else if (strcmp(ext, "png") == 0) { + result = + stbi_write_png(filename, image->width, image->height, image->channels, + image->image_data, image->width * image->channels); + } else if (strcmp(ext, "bmp") == 0) { + result = stbi_write_bmp(filename, image->width, image->height, + image->channels, image->image_data); + } else if (strcmp(ext, "tga") == 0) { + result = stbi_write_tga(filename, image->width, image->height, + image->channels, image->image_data); + } else { + fprintf(stderr, "Error: unsupported format '%s'\n", ext); + return -1; + } + + if (result == 0) { + fprintf(stderr, "Error: could not save image '%s'\n", filename); + return -1; + } + return 0; +} + +image_t *create_empty_image(int height, int width, int channels) { + size_t image_size = width * height * channels; + unsigned char *new_image_data = + (unsigned char *)calloc(image_size, sizeof(unsigned char)); + if (!new_image_data) { + fprintf(stderr, "Error: memory allocation failed for image data.\n"); + return NULL; + } + + image_t *new_image = (image_t *)malloc(sizeof(image_t)); + if (!new_image) { + fprintf(stderr, "Error: memory allocation failed for image structure.\n"); + free(new_image_data); + return NULL; + } + + new_image->height = height; + new_image->width = width; + new_image->channels = channels; + new_image->image_data = new_image_data; + return new_image; +} + +const char *generate_filename(const char *filename, const char *filter_name) { + static char output[512]; + + if (!filename || !filter_name) { + fprintf(stderr, "Error: NULL pointer in generate_filename\n"); + return NULL; + } + + const char *dot = strrchr(filename, '.'); + if (!dot) { + fprintf(stderr, "Error: invalid filename '%s': missing file extension\n", + filename); + return NULL; + } + + int len = dot - filename; + if (len >= (int)sizeof(output)) { + fprintf(stderr, "Error: filename too long\n"); + return NULL; + } + + char name_no_ext[256]; + if (len >= (int)sizeof(name_no_ext)) { + len = sizeof(name_no_ext) - 1; + } + memcpy(name_no_ext, filename, len); + name_no_ext[len] = '\0'; + + snprintf(output, sizeof(output), "%s_%s%s", name_no_ext, filter_name, dot); + + return output; +} + +void free_image(image_t *image) { + if (image) { + if (image->image_data) { + stbi_image_free(image->image_data); + } + free(image); + } +} diff --git a/src/utils/image_io.h b/src/utils/image_io.h new file mode 100644 index 0000000..325748e --- /dev/null +++ b/src/utils/image_io.h @@ -0,0 +1,14 @@ +#pragma once + +typedef struct { + unsigned char *image_data; + int height; + int width; + int channels; +} image_t; + +image_t *load_image(const char *filename); +image_t *create_empty_image(int height, int width, int channels); +int store_image(const char *filename, image_t *image); +void free_image(image_t *image); +const char *generate_filename(const char *filename, const char *filter_name); From 4e4394dde6bb9e22f5aece16605da82260c944cd Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 22:02:55 +0300 Subject: [PATCH 02/11] feat: add filters --- src/utils/filters.c | 98 +++++++++++++++++++++++++++++++++++++++++++++ src/utils/filters.h | 13 ++++++ 2 files changed, 111 insertions(+) create mode 100644 src/utils/filters.c create mode 100644 src/utils/filters.h diff --git a/src/utils/filters.c b/src/utils/filters.c new file mode 100644 index 0000000..6ab0e76 --- /dev/null +++ b/src/utils/filters.c @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "filters.h" + +// clang-format off +const double motion_blur_arr[81] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1}; + +const double blur_arr[25] = {0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0}; + +const double gaus_blur_arr[25] = {1, 4, 6, 4, 1, + 4, 16, 24, 16, + 4, 6, 24, 36, 24, + 6, 4, 16, 24, 16, + 4, 1, 4, 6, 4, 1}; + +const double sharpen_arr[25] = {-1, -1, -1, -1, -1, + -1, 2, 2, 2, -1, + -1, 2, 8, 2, -1, + -1, 2, 2, 2, -1, + -1, -1, -1, -1, -1}; + +const double emboss_arr[25] = {-1, -1, -1, -1, 0, + -1, -1, -1, 0, 1, + -1, -1, 0, 1, 1, + -1, 0, 1, 1, 1, + 0, 1, 1, 1, 1}; + +const double find_edges_arr[9] = {-1, -1, -1, + -1, 8, -1, + -1, -1, -1}; +// clang-format on + +filter_t *init_filter(int size, double bias, double factor, + const double *filter_arr, const char *name) { + filter_t *filter = (filter_t *)malloc(sizeof(filter_t)); + if (!filter) { + fprintf(stderr, "Error: malloc failed for filter structure.\n"); + return NULL; + } + + filter->filter_arr = (double *)malloc(size * size * sizeof(double)); + if (!filter->filter_arr) { + fprintf(stderr, "Error: malloc failed for filter array.\n"); + free(filter); + return NULL; + } + + filter->size = size; + filter->bias = bias; + filter->factor = factor; + filter->name = name; + memcpy(filter->filter_arr, filter_arr, size * size * sizeof(double)); + return filter; +} + +filter_t *create_filter(filter_name name) { + switch (name) { + case (BLUR): + return init_filter(5, 0.0, 1.0 / 13.0, blur_arr, "blur"); + case (MOTION_BLUR): + return init_filter(9, 0.0, 1.0 / 9.0, motion_blur_arr, "motion"); + case (GAUSSIAN_BLUR): + return init_filter(5, 0.0, 1.0 / 256.0, gaus_blur_arr, "gaussian"); + case (FIND_EDGES): + return init_filter(3, 0.0, 1.0, find_edges_arr, "edges"); + case (EMBOSS): + return init_filter(5, 128.0, 1.0, emboss_arr, "emboss"); + case (SHARPEN): + return init_filter(5, 0.0, 1.0 / 8.0, sharpen_arr, "sharpen"); + default: + fprintf(stderr, "Error: unknown filter.\n"); + return NULL; + } +} + +void free_filter(filter_t *filter) { + if (filter) { + if (filter->filter_arr) { + free(filter->filter_arr); + } + free(filter); + } +} diff --git a/src/utils/filters.h b/src/utils/filters.h new file mode 100644 index 0000000..1d623b9 --- /dev/null +++ b/src/utils/filters.h @@ -0,0 +1,13 @@ +#pragma once +#include "parser_args.h" + +typedef struct { + int size; + double bias; + double factor; + double *filter_arr; + const char *name; +} filter_t; + +filter_t *create_filter(filter_name name); +void free_filter(filter_t *filter); From 43e7316667b2d90be388132727a9ea06c8d41aa2 Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 22:05:01 +0300 Subject: [PATCH 03/11] feat: add args parser --- src/main.c | 34 ++++++++ src/utils/parser_args.c | 181 ++++++++++++++++++++++++++++++++++++++++ src/utils/parser_args.h | 29 +++++++ 3 files changed, 244 insertions(+) create mode 100644 src/main.c create mode 100644 src/utils/parser_args.c create mode 100644 src/utils/parser_args.h diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..43626d9 --- /dev/null +++ b/src/main.c @@ -0,0 +1,34 @@ +#include +#include + +#include "algo/process_image.h" + +args_t *args = NULL; + +int main(int argc, char **argv) { + args = (args_t *)calloc(1, sizeof(args_t)); + if (!args) { + fprintf(stderr, "Error: Cannot allocate args structure.\n"); + return -1; + } + + int ret = parse_args(argc, argv, args); + if (ret < 0) { + free_args(args); + return -1; + } + + if (args->help_flag) { + free_args(args); + return 0; + } + + ret = process_image(args); + + if (ret < 0) { + free_args(args); + return -1; + } + free_args(args); + return 0; +} diff --git a/src/utils/parser_args.c b/src/utils/parser_args.c new file mode 100644 index 0000000..d7a4185 --- /dev/null +++ b/src/utils/parser_args.c @@ -0,0 +1,181 @@ +#include +#include +#include + +#include "parser_args.h" + +#define INITIAL_CAPACITY 8 + +#define USAGE_PRINT \ + fprintf(stderr, \ + "Usage: %s --filter= --mode= [--help | -h]" \ + "\n", \ + argv[0]); \ + fprintf(stderr, "Use '%s --help' for more information.\n", argv[0]); + +// Basic check: not empty and has extension +// Actual file existence and format validation are handled by load_image() +bool is_file(char *filename) { return (filename && strchr(filename, '.')); } + +void init_args(args_t *args) { + args->filter = INVALID; + args->help_flag = false; + args->filenames = NULL; + args->images_number = 0; + args->mode = MODE_INVALID; +} + +filter_name parse_filter_arg(char *filter_str) { + if (strcmp(filter_str, "blur") == 0) { + return BLUR; + } else if (strcmp(filter_str, "motion") == 0) { + return MOTION_BLUR; + } else if (strcmp(filter_str, "gaussian") == 0) { + return GAUSSIAN_BLUR; + } else if (strcmp(filter_str, "edges") == 0) { + return FIND_EDGES; + } else if (strcmp(filter_str, "emboss") == 0) { + return EMBOSS; + } else if (strcmp(filter_str, "sharpen") == 0) { + return SHARPEN; + } + return INVALID; +} + +conv_mode parse_mode_arg(char *mode_str) { + if (strcmp(mode_str, "seq") == 0) { + return MODE_SEQ; + } + return MODE_INVALID; +} + +static int add_filename(args_t *args, char *filename) { + static size_t capacity = 0; + + if (args->filenames == NULL) { + capacity = INITIAL_CAPACITY; + args->filenames = malloc(capacity * sizeof(char *)); + if (!args->filenames) { + fprintf(stderr, "Error: memory allocation failed while adding file\n"); + return -1; + } + } + + if (args->images_number >= capacity) { + capacity *= 2; + char **new = realloc(args->filenames, capacity * sizeof(char *)); + if (!new) { + fprintf(stderr, "Error: memory allocation failed while adding file\n"); + return -1; + } + args->filenames = new; + } + + args->filenames[args->images_number++] = filename; + return 0; +} + +void print_help(char *argv[]) { + printf("Usage: %s --filter= --mode= [--help | -h]" + "\n\n", + argv[0]); + + printf("Options:\n"); + printf(" --filter= Filter to apply\n"); + printf(" Available: blur, motion, gaussian, edges, emboss, " + "sharpen\n\n"); + printf(" --mode= Parallelization strategy\n"); + printf(" seq - Sequential\n"); + printf(" --help, -h Show this help message\n\n"); +} + +int parse_args(int argc, char *argv[], args_t *args) { + if (argc < 2) { + fprintf(stderr, "Error: missing required arguments\n"); + USAGE_PRINT + return -1; + } + + if (!args) { + fprintf(stderr, "Error: args structure cannot be NULL\n"); + return -1; + } + + init_args(args); + + for (int i = 1; i < argc; i++) { + if (strncmp(argv[i], "--filter=", 9) == 0) { + char *filter_str = argv[i] + 9; + if (strlen(filter_str) == 0) { + fprintf(stderr, "Error: --filter requires a value\n"); + fprintf( + stderr, + "Valid filters: blur, motion, gaussian, edges, emboss, sharpen\n"); + return -1; + } + args->filter = parse_filter_arg(filter_str); + if (args->filter == INVALID) { + fprintf(stderr, "Error: invalid filter '%s'\n", filter_str); + fprintf( + stderr, + "Valid filters: blur, motion, gaussian, edges, emboss, sharpen\n"); + return -1; + } + } else if (strncmp(argv[i], "--mode=", 7) == 0) { + char *mode = argv[i] + 7; + if (strlen(mode) == 0) { + fprintf(stderr, "Error: --mode requires a value\n"); + fprintf(stderr, "Valid modes: seq\n"); + return -1; + } + args->mode = parse_mode_arg(mode); + if (args->mode == MODE_INVALID) { + fprintf(stderr, "Error: invalid mode '%s'\n", mode); + fprintf(stderr, "Valid modes: seq\n"); + return -1; + } + } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + print_help(argv); + args->help_flag = true; + return 0; + } else if (strncmp(argv[i], "-", 1) == 0) { + fprintf(stderr, "Error: unknown option '%s'\n", argv[i]); + USAGE_PRINT + return -1; + } else { + if (is_file(argv[i])) { + if (add_filename(args, argv[i]) < 0) { + return -1; + } + } else { + fprintf(stderr, "Error: invalid argument '%s'\n", argv[i]); + USAGE_PRINT + return -1; + } + } + } + + if (args->filter == INVALID) { + fprintf(stderr, "Error: --filter is required\n"); + return -1; + } + if (args->mode == MODE_INVALID) { + fprintf(stderr, "Error: --mode is required\n"); + return -1; + } + if (args->filenames == NULL || args->images_number == 0) { + fprintf(stderr, "Error: no input file\n"); + return -1; + } + + return 0; +} + +void free_args(args_t *args) { + if (args) { + if (args->filenames) { + free(args->filenames); + } + free(args); + } +} \ No newline at end of file diff --git a/src/utils/parser_args.h b/src/utils/parser_args.h new file mode 100644 index 0000000..51a06ea --- /dev/null +++ b/src/utils/parser_args.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +typedef enum { + INVALID = -1, + BLUR, + MOTION_BLUR, + GAUSSIAN_BLUR, + FIND_EDGES, + EMBOSS, + SHARPEN, +} filter_name; + +typedef enum { + MODE_INVALID = -1, + MODE_SEQ, +} conv_mode; + +typedef struct { + char **filenames; + size_t images_number; + conv_mode mode; + filter_name filter; + bool help_flag; +} args_t; + +int parse_args(int argc, char *argv[], args_t *args); +void free_args(args_t *args); From 9bf556efe144ae0ca6c672f01308b0761c648fbb Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 22:08:31 +0300 Subject: [PATCH 04/11] feat: add sequential convol --- src/algo/convolution.c | 71 ++++++++++++++++++++++++++++++++++++++ src/algo/convolution.h | 6 ++++ src/algo/process_image.c | 74 ++++++++++++++++++++++++++++++++++++++++ src/algo/process_image.h | 4 +++ 4 files changed, 155 insertions(+) create mode 100644 src/algo/convolution.c create mode 100644 src/algo/convolution.h create mode 100644 src/algo/process_image.c create mode 100644 src/algo/process_image.h diff --git a/src/algo/convolution.c b/src/algo/convolution.c new file mode 100644 index 0000000..4de1f48 --- /dev/null +++ b/src/algo/convolution.c @@ -0,0 +1,71 @@ +#include +#include + +#include "utils/filters.h" +#include "utils/image_io.h" + +#define BOUND(value, min, max) \ + ((value) < (min) ? (min) : ((value) > (max) ? (max) : (value))) + +static inline void process_pixel(int x, int y, int width, int height, + int channels, unsigned char *image_data, + unsigned char *new_image_data, + double *filter_arr, int filter_size, + int offset, double factor, double bias) { + double red = 0.0, green = 0.0, blue = 0.0; + for (int filter_y = 0; filter_y < filter_size; ++filter_y) { + for (int filter_x = 0; filter_x < filter_size; ++filter_x) { + int image_x = (x - offset + filter_x + width) % width; + int image_y = (y - offset + filter_y + height) % height; + int idx = (image_y * width + image_x) * channels; + double filter_val = filter_arr[filter_y * filter_size + filter_x]; + + red += image_data[idx] * filter_val; + green += image_data[idx + 1] * filter_val; + blue += image_data[idx + 2] * filter_val; + } + } + + int dst_idx = (y * width + x) * channels; + + double res_red = factor * red + bias; + double res_green = factor * green + bias; + double res_blue = factor * blue + bias; + new_image_data[dst_idx] = (unsigned char)BOUND(res_red, 0, 255); + new_image_data[dst_idx + 1] = (unsigned char)BOUND(res_green, 0, 255); + new_image_data[dst_idx + 2] = (unsigned char)BOUND(res_blue, 0, 255); +} + +image_t *seq_convolution(image_t *image, filter_t *filter) { + if (image == NULL || filter == NULL) { + fprintf(stderr, "Error: NULL pointer in convolution.\n"); + return NULL; + } + + int height = image->height; + int width = image->width; + int channels = image->channels; + unsigned char *image_data = image->image_data; + + double *filter_arr = filter->filter_arr; + int filter_size = filter->size; + + image_t *new_image = create_empty_image(height, width, channels); + if (!new_image) { + fprintf(stderr, "Error: Cannot create new image.\n"); + return NULL; + } + unsigned char *new_image_data = new_image->image_data; + + int offset = filter_size / 2; + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + process_pixel(x, y, width, height, channels, image_data, new_image_data, + filter_arr, filter_size, offset, filter->factor, + filter->bias); + } + } + + return new_image; +} diff --git a/src/algo/convolution.h b/src/algo/convolution.h new file mode 100644 index 0000000..89949ba --- /dev/null +++ b/src/algo/convolution.h @@ -0,0 +1,6 @@ +#pragma once + +#include "utils/filters.h" +#include "utils/image_io.h" + +image_t *seq_convolution(image_t *image, filter_t *filter); diff --git a/src/algo/process_image.c b/src/algo/process_image.c new file mode 100644 index 0000000..9ffe82e --- /dev/null +++ b/src/algo/process_image.c @@ -0,0 +1,74 @@ +#include + +#include "convolution.h" + +#define FREE_IMAGES \ + free_image(image); \ + free_image(new_image) + +int process_image(args_t *args) { + if (!args) { + fprintf(stderr, "Error: args are NULL\n"); + return -1; + } + + filter_t *filter = create_filter(args->filter); + if (!filter) { + fprintf(stderr, "Error: failed to create filter\n"); + return -1; + } + + const char *filter_name = filter->name; + conv_mode mode = args->mode; + + for (size_t i = 0; i < args->images_number; i++) { + const char *filename = args->filenames[i]; + image_t *image = NULL; + image_t *new_image = NULL; + + image = load_image(filename); + if (!image) { + free_filter(filter); + return -1; + } + + switch (mode) { + case MODE_SEQ: + new_image = seq_convolution(image, filter); + break; + + default: + fprintf(stderr, "Error: unknown mode %d\n", mode); + FREE_IMAGES; + free_filter(filter); + return -1; + } + + if (!new_image) { + fprintf(stderr, "Error: convolution failed\n"); + FREE_IMAGES; + free_filter(filter); + return -1; + } + + const char *new_filename = generate_filename(filename, filter_name); + if (!new_filename) { + fprintf(stderr, "Error: failed to generate output filename\n"); + FREE_IMAGES; + free_filter(filter); + return -1; + } + + int ret = store_image(new_filename, new_image); + if (ret < 0) { + FREE_IMAGES; + free_filter(filter); + return -1; + } + + FREE_IMAGES; + } + + free_filter(filter); + return 0; +} diff --git a/src/algo/process_image.h b/src/algo/process_image.h new file mode 100644 index 0000000..5e9fd15 --- /dev/null +++ b/src/algo/process_image.h @@ -0,0 +1,4 @@ +#pragma once +#include "utils/parser_args.h" + +int process_image(args_t *args); From 18636cb0d8d7c180e7b25d22a7e945fc5a76dd3c Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 22:14:57 +0300 Subject: [PATCH 05/11] build: add Makefile --- Makefile | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..16ed060 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +CC := gcc +CFLAGS_COMMON := -Wall -Wextra -Wpedantic -I./src -I./deps +CFLAGS_DEBUG := -O0 -g +CFLAGS_RELEASE := -O2 + +CFLAGS_ASAN := -fsanitize=address -g -O0 -fno-omit-frame-pointer +LDFLAGS_ASAN := -fsanitize=address + +CFLAGS := $(CFLAGS_COMMON) $(CFLAGS_DEBUG) +CFLAGS_BENCH := $(CFLAGS_COMMON) $(CFLAGS_RELEASE) -DNDEBUG +LDFLAGS := -lm + +SRC := $(shell find src -name '*.c' ! -name 'main.c' ) +APP_SRC := $(SRC) src/main.c + +HDR := $(shell find src -name '*.h') $(shell find tests -name '*.h' 2>/dev/null || true) + +TARGET := build/convol + +.PHONY: build clean fmt help asan + +help: + @echo "Available targets:" + @echo " build - Build main program" + @echo " asan - Build with AddressSanitizer" + @echo " clean - Remove build directory" + @echo " fmt - Format code" + +build: $(TARGET) + +$(TARGET): $(APP_SRC) $(HDR) + @mkdir -p build + $(CC) $(CFLAGS) $(APP_SRC) -o $@ $(LDFLAGS) + +asan: clean + @mkdir -p build + $(CC) $(CFLAGS) $(CFLAGS_ASAN) $(APP_SRC) -o $(TARGET)_asan $(LDFLAGS) $(LDFLAGS_ASAN) + +clean: + rm -rf build + +fmt: + clang-format -i $(SRC) $(APP_SRC) $(HDR) From 1524066febee932d52696d4f12023b5a74f93a5a Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 22:15:12 +0300 Subject: [PATCH 06/11] docs: add README --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..917e8b8 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Convolution + +Image convolution tool with multiple parallelization strategies. + +## Features + +- **Filters**: `blur`, `sharpen`, `gaussian`, `motion`, `edge`, `emboss` +- **Modes**: + - `seq` - sequential +- **Formats**: `jpeg`, `jpg`, `png`, `bmp`, `tga` + +## Build + +```bash +make build +```` + +## Usage + +```bash +./build/convol --filter= --mode= [--help | -h] +```` + +## Examples + +```bash +# Sequential blur on an image +./build/convol image.jpg --filter=blur --mode=seq +`` From 26324d8f1a7ec51424c15a860fba20a73c53d120 Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 23:06:15 +0300 Subject: [PATCH 07/11] feat: add parallel convol --- src/algo/convolution.c | 162 +++++++++++++++++++++++++++++++++++++++ src/algo/convolution.h | 4 + src/algo/process_image.c | 16 ++++ 3 files changed, 182 insertions(+) diff --git a/src/algo/convolution.c b/src/algo/convolution.c index 4de1f48..6330422 100644 --- a/src/algo/convolution.c +++ b/src/algo/convolution.c @@ -1,3 +1,4 @@ +#include #include #include @@ -69,3 +70,164 @@ image_t *seq_convolution(image_t *image, filter_t *filter) { return new_image; } + +image_t *parallel_pixel_convolution(image_t *image, filter_t *filter) { + if (image == NULL || filter == NULL) { + fprintf(stderr, "Error: NULL pointer in convolution.\n"); + return NULL; + } + + int height = image->height; + int width = image->width; + int channels = image->channels; + unsigned char *image_data = image->image_data; + + double *filter_arr = filter->filter_arr; + int filter_size = filter->size; + + image_t *new_image = create_empty_image(height, width, channels); + if (!new_image) { + fprintf(stderr, "Error: Cannot create new image.\n"); + return NULL; + } + unsigned char *new_image_data = new_image->image_data; + + int offset = filter_size / 2; + +#pragma omp parallel for collapse(2) + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + process_pixel(x, y, width, height, channels, image_data, new_image_data, + filter_arr, filter_size, offset, filter->factor, + filter->bias); + } + } + + return new_image; +} + +image_t *parallel_row_convolution(image_t *image, filter_t *filter) { + if (image == NULL || filter == NULL) { + fprintf(stderr, "Error: NULL pointer in convolution.\n"); + + return NULL; + } + + int height = image->height; + int width = image->width; + int channels = image->channels; + unsigned char *image_data = image->image_data; + + double *filter_arr = filter->filter_arr; + int filter_size = filter->size; + + image_t *new_image = create_empty_image(height, width, channels); + if (!new_image) { + fprintf(stderr, "Error: Cannot create new image.\n"); + return NULL; + } + unsigned char *new_image_data = new_image->image_data; + + int offset = filter_size / 2; + +#pragma omp parallel for + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + process_pixel(x, y, width, height, channels, image_data, new_image_data, + filter_arr, filter_size, offset, filter->factor, + filter->bias); + } + } + + return new_image; +} + +image_t *parallel_column_convolution(image_t *image, filter_t *filter) { + if (image == NULL || filter == NULL) { + fprintf(stderr, "Error: NULL pointer in convolution.\n"); + return NULL; + } + + int height = image->height; + int width = image->width; + int channels = image->channels; + unsigned char *image_data = image->image_data; + + double *filter_arr = filter->filter_arr; + int filter_size = filter->size; + + image_t *new_image = create_empty_image(height, width, channels); + if (!new_image) { + fprintf(stderr, "Error: Cannot create new image.\n"); + return NULL; + } + unsigned char *new_image_data = new_image->image_data; + + int offset = filter_size / 2; + +#pragma omp parallel for + for (int x = 0; x < width; ++x) { + for (int y = 0; y < height; ++y) { + process_pixel(x, y, width, height, channels, image_data, new_image_data, + filter_arr, filter_size, offset, filter->factor, + filter->bias); + } + } + + return new_image; +} + +image_t *parallel_block_convolution(image_t *image, filter_t *filter) { + if (image == NULL || filter == NULL) { + fprintf(stderr, "Error: NULL pointer in convolution.\n"); + return NULL; + } + + // The block size is now fixed at 64 + int block_size = 64; + + int height = image->height; + int width = image->width; + int channels = image->channels; + unsigned char *image_data = image->image_data; + + double *filter_arr = filter->filter_arr; + int filter_size = filter->size; + + image_t *new_image = create_empty_image(height, width, channels); + if (!new_image) { + fprintf(stderr, "Error: Cannot create new image.\n"); + return NULL; + } + unsigned char *new_image_data = new_image->image_data; + + int offset = filter_size / 2; + + int block_width = block_size; + int block_height = block_size; + + int blocks_x = (width + block_width - 1) / block_width; + int blocks_y = (height + block_height - 1) / block_height; + +#pragma omp parallel for collapse(2) + for (int by = 0; by < blocks_y; by++) { + for (int bx = 0; bx < blocks_x; bx++) { + int start_y = by * block_height; + int start_x = bx * block_width; + int end_y = + (start_y + block_height > height) ? height : start_y + block_height; + int end_x = + (start_x + block_width > width) ? width : start_x + block_width; + + for (int y = start_y; y < end_y; y++) { + for (int x = start_x; x < end_x; x++) { + process_pixel(x, y, width, height, channels, image_data, + new_image_data, filter_arr, filter_size, offset, + filter->factor, filter->bias); + } + } + } + } + + return new_image; +} diff --git a/src/algo/convolution.h b/src/algo/convolution.h index 89949ba..38bcd75 100644 --- a/src/algo/convolution.h +++ b/src/algo/convolution.h @@ -4,3 +4,7 @@ #include "utils/image_io.h" image_t *seq_convolution(image_t *image, filter_t *filter); +image_t *parallel_pixel_convolution(image_t *image, filter_t *filter); +image_t *parallel_row_convolution(image_t *image, filter_t *filter); +image_t *parallel_column_convolution(image_t *image, filter_t *filter); +image_t *parallel_block_convolution(image_t *image, filter_t *filter); diff --git a/src/algo/process_image.c b/src/algo/process_image.c index 9ffe82e..343f152 100644 --- a/src/algo/process_image.c +++ b/src/algo/process_image.c @@ -37,6 +37,22 @@ int process_image(args_t *args) { new_image = seq_convolution(image, filter); break; + case MODE_ROW: + new_image = parallel_row_convolution(image, filter); + break; + + case MODE_PIXEL: + new_image = parallel_pixel_convolution(image, filter); + break; + + case MODE_COLUMN: + new_image = parallel_column_convolution(image, filter); + break; + + case MODE_BLOCK: + new_image = parallel_block_convolution(image, filter); + break; + default: fprintf(stderr, "Error: unknown mode %d\n", mode); FREE_IMAGES; From 87fe54dba9525d7fa6ad5428c964c82f98bf32be Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 23:09:30 +0300 Subject: [PATCH 08/11] feat: add parallel convol parsing --- src/utils/parser_args.c | 18 +++++++++++++++--- src/utils/parser_args.h | 4 ++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/utils/parser_args.c b/src/utils/parser_args.c index d7a4185..e43a661 100644 --- a/src/utils/parser_args.c +++ b/src/utils/parser_args.c @@ -45,6 +45,14 @@ filter_name parse_filter_arg(char *filter_str) { conv_mode parse_mode_arg(char *mode_str) { if (strcmp(mode_str, "seq") == 0) { return MODE_SEQ; + } else if (strcmp(mode_str, "pixel") == 0) { + return MODE_PIXEL; + } else if (strcmp(mode_str, "row") == 0) { + return MODE_ROW; + } else if (strcmp(mode_str, "column") == 0) { + return MODE_COLUMN; + } else if (strcmp(mode_str, "block") == 0) { + return MODE_BLOCK; } return MODE_INVALID; } @@ -86,6 +94,10 @@ void print_help(char *argv[]) { "sharpen\n\n"); printf(" --mode= Parallelization strategy\n"); printf(" seq - Sequential\n"); + printf(" row - Parallel by rows\n"); + printf(" column - Parallel by columns\n"); + printf(" pixel - Parallel by individual pixels\n"); + printf(" block - Parallel by blocks (64x64)\n\n"); printf(" --help, -h Show this help message\n\n"); } @@ -125,13 +137,13 @@ int parse_args(int argc, char *argv[], args_t *args) { char *mode = argv[i] + 7; if (strlen(mode) == 0) { fprintf(stderr, "Error: --mode requires a value\n"); - fprintf(stderr, "Valid modes: seq\n"); + fprintf(stderr, "Valid modes: seq, pixel, row, column, block\n"); return -1; } args->mode = parse_mode_arg(mode); if (args->mode == MODE_INVALID) { fprintf(stderr, "Error: invalid mode '%s'\n", mode); - fprintf(stderr, "Valid modes: seq\n"); + fprintf(stderr, "Valid modes: seq, pixel, row, column, block\n"); return -1; } } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { @@ -178,4 +190,4 @@ void free_args(args_t *args) { } free(args); } -} \ No newline at end of file +} diff --git a/src/utils/parser_args.h b/src/utils/parser_args.h index 51a06ea..bfcb4ae 100644 --- a/src/utils/parser_args.h +++ b/src/utils/parser_args.h @@ -15,6 +15,10 @@ typedef enum { typedef enum { MODE_INVALID = -1, MODE_SEQ, + MODE_PIXEL, + MODE_ROW, + MODE_COLUMN, + MODE_BLOCK, } conv_mode; typedef struct { From f20abbbd2f657d2c29eb3b73027f042eff82d92a Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 23:16:56 +0300 Subject: [PATCH 09/11] test: add tests & benchmarks --- benchmark_res/plot.py | 57 ++++++++++++ images/test_image.jpg | Bin 0 -> 41697 bytes src/benchmark.c | 196 ++++++++++++++++++++++++++++++++++++++++++ tests/tests.c | 109 +++++++++++++++++++++++ 4 files changed, 362 insertions(+) create mode 100644 benchmark_res/plot.py create mode 100644 images/test_image.jpg create mode 100644 src/benchmark.c create mode 100644 tests/tests.c diff --git a/benchmark_res/plot.py b/benchmark_res/plot.py new file mode 100644 index 0000000..90998e3 --- /dev/null +++ b/benchmark_res/plot.py @@ -0,0 +1,57 @@ +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd + +modes = [] +data = [] + +filename = "result_small" + +def read_benchmark_data_pandas(filename): + df = pd.read_csv(filename + ".csv", comment='#') + + modes = df['mode'].tolist() + value_cols = [col for col in df.columns if col != 'mode'] + data = [df[col].tolist() for col in value_cols] + data = list(zip(*data)) + + return modes, data + +modes, data = read_benchmark_data_pandas(filename) + +fig, ax = plt.subplots(figsize=(8, 6)) + +bp = ax.boxplot( + data, + positions=np.arange(len(data)) + 1, + widths=0.6, + patch_artist=True, + showfliers=False, +) + +colors = ["#FF9999", "#99FF99", "#9999FF", "#FFCC99", "#CC99FF", "#66CCCC"] +for patch, color in zip(bp["boxes"], colors * 10): + patch.set_facecolor(color) + patch.set_alpha(0.6) + +for i, d in enumerate(data, start=1): + x = np.random.normal(i, 0.04, size=len(d)) + ax.plot(x, d, "o", markersize=5, alpha=0.3, color="black") + +ax.set_xticks(np.arange(1, len(modes) + 1)) +ax.set_xticklabels(modes, rotation=20) +ax.set_ylabel("Time (sec)") +ax.set_title("Benchmark: motion (9x9) | 736x469") + +plt.grid(True, axis="y", linestyle="--", alpha=0.6) +plt.tight_layout() + +plt.savefig(filename + ".png", dpi=200) +plt.show() + +print("\n=== Benchmark Summary ===") +print(f"{'Mode':<10} {'Min':<10} {'Median':<10} {'Max':<10}") +print("-" * 50) +for i, mode in enumerate(modes): + vals = data[i] + print(f"{mode:<10} {np.min(vals):<10.6f} {np.median(vals):<10.6f} {np.max(vals):<10.6f}") \ No newline at end of file diff --git a/images/test_image.jpg b/images/test_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5bd2d03064d4a9fd75a9a43d81c41e217a884479 GIT binary patch literal 41697 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 literal 0 HcmV?d00001 diff --git a/src/benchmark.c b/src/benchmark.c new file mode 100644 index 0000000..c0f19f1 --- /dev/null +++ b/src/benchmark.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include +#include + +#include "algo/convolution.h" +#include "utils/filters.h" +#include "utils/image_io.h" + +#define NUM_RUNS 10 + +#define BENCH_EXEC(mode) \ + for (size_t i = 0; i < NUM_RUNS; i++) { \ + double start = omp_get_wtime(); \ + image_t *new_image = mode(image, filter); \ + double end = omp_get_wtime(); \ + res[i] = end - start; \ + free_image(new_image); \ + } + +double average(double *res) { + double sum = 0; + for (size_t i = 0; i < NUM_RUNS; i++) + sum += res[i]; + return sum / NUM_RUNS; +} + +static void print_results(const char *name, double *res) { + printf("%-8s", name); + for (int i = 0; i < NUM_RUNS; i++) + printf("%s%.4f", (i == 0) ? " " : ", ", res[i]); + printf("\n"); +} + +static void save_results_csv(image_t *image, char *filter_name, double *seq_res, + double *row_res, double *pixel_res, + double *column_res, double *block_res) { + + FILE *f = fopen("./benchmark_res/resul1t.csv", "w"); + if (f == NULL) { + perror("Failed to create result file"); + return; + } + + fprintf(f, "# Benchmark Results\n"); + fprintf(f, "# Filter: %s\n", filter_name); + fprintf(f, "# Image: %dx%d, %d channels\n", image->width, image->height, + image->channels); + fprintf(f, "# Runs: %d\n", NUM_RUNS); + fprintf(f, "#\n"); + + fprintf(f, "mode"); + for (int i = 1; i <= NUM_RUNS; i++) { + fprintf(f, ",run_%d", i); + } + fprintf(f, "\n"); + + fprintf(f, "seq: %.6f", average(seq_res)); + for (int i = 0; i < NUM_RUNS; i++) + fprintf(f, ",%.6f", seq_res[i]); + fprintf(f, "\n"); + + fprintf(f, "row: %.6f", average(row_res)); + for (int i = 0; i < NUM_RUNS; i++) + fprintf(f, ",%.6f", row_res[i]); + fprintf(f, "\n"); + + fprintf(f, "pixel: %.6f", average(pixel_res)); + for (int i = 0; i < NUM_RUNS; i++) + fprintf(f, ",%.6f", pixel_res[i]); + fprintf(f, "\n"); + + fprintf(f, "column: %.6f", average(column_res)); + for (int i = 0; i < NUM_RUNS; i++) + fprintf(f, ",%.6f", column_res[i]); + fprintf(f, "\n"); + + fprintf(f, "block: %.6f", average(block_res)); + for (int i = 0; i < NUM_RUNS; i++) + fprintf(f, ",%.6f", block_res[i]); + fprintf(f, "\n"); + + fclose(f); + printf("\nResults saved\n"); +} + +void run_benchmark(image_t *image, filter_t *filter, conv_mode mode, + double *res) { + switch (mode) { + case MODE_SEQ: + BENCH_EXEC(seq_convolution); + break; + + case MODE_ROW: + BENCH_EXEC(parallel_row_convolution); + break; + + case MODE_PIXEL: + BENCH_EXEC(parallel_pixel_convolution); + break; + + case MODE_COLUMN: + BENCH_EXEC(parallel_column_convolution); + break; + + case MODE_BLOCK: + BENCH_EXEC(parallel_block_convolution); + break; + + default: + fprintf(stderr, "Error: unknown mode %d\n", mode); + return; + } +} + +// Usage: make bench FILTER= IMAGE= +int main(int argc, char **argv) { + if (argc < 3) { + fprintf(stderr, "Error: filter and image are required\n"); + return -1; + } + + filter_t *filter = NULL; + if (strcmp(argv[1], "blur") == 0) { + filter = create_filter(BLUR); + } else if (strcmp(argv[1], "motion") == 0) { + filter = create_filter(MOTION_BLUR); + } else if (strcmp(argv[1], "gaussian") == 0) { + filter = create_filter(GAUSSIAN_BLUR); + } else if (strcmp(argv[1], "edge") == 0) { + filter = create_filter(FIND_EDGES); + } else if (strcmp(argv[1], "emboss") == 0) { + filter = create_filter(EMBOSS); + } else if (strcmp(argv[1], "sharpen") == 0) { + filter = create_filter(SHARPEN); + } + + if (!filter) { + fprintf(stderr, "Error: failed to create filter\n"); + return -1; + } + + image_t *image = load_image(argv[2]); + if (!image) { + fprintf(stderr, "Error: failed to load image '%s'\n", argv[2]); + free_filter(filter); + return -1; + } + + printf("========================================\n"); + printf("Benchmark Configuration\n"); + printf("========================================\n"); + printf("Image: %s (%dx%d, %d channels)\n", argv[2], image->width, + image->height, image->channels); + printf("Filter: %s (size: %d)\n", argv[1], filter->size); + printf("Runs: %d\n", NUM_RUNS); + printf("========================================\n\n"); + + double seq_res[NUM_RUNS]; + double pixel_res[NUM_RUNS]; + double row_res[NUM_RUNS]; + double column_res[NUM_RUNS]; + double block_res[NUM_RUNS]; + + printf("Running benchmarks...\n\n"); + + run_benchmark(image, filter, MODE_SEQ, seq_res); + run_benchmark(image, filter, MODE_ROW, row_res); + run_benchmark(image, filter, MODE_PIXEL, pixel_res); + run_benchmark(image, filter, MODE_COLUMN, column_res); + run_benchmark(image, filter, MODE_BLOCK, block_res); + + printf("Results (seconds per run):\n"); + printf("----------------------------------------\n"); + print_results("Seq:", seq_res); + print_results("Row:", row_res); + print_results("Pixel:", pixel_res); + print_results("Column:", column_res); + print_results("Block:", block_res); + printf("----------------------------------------\n\n"); + + printf("Average times:\n"); + printf(" Seq:.....................%.4f\n", average(seq_res)); + printf(" Pixel:...................%.4f\n", average(pixel_res)); + printf(" Row:.....................%.4f\n", average(row_res)); + printf(" Column:..................%.4f\n", average(column_res)); + printf(" Block:...................%.4f\n", average(block_res)); + + save_results_csv(image, argv[1], seq_res, row_res, pixel_res, column_res, + block_res); + + free_filter(filter); + free_image(image); + return 0; +} \ No newline at end of file diff --git a/tests/tests.c b/tests/tests.c new file mode 100644 index 0000000..38914c8 --- /dev/null +++ b/tests/tests.c @@ -0,0 +1,109 @@ +// clang-format off +#include +#include +#include +#include +#include +#include + +#include "algo/convolution.h" +#include "utils/filters.h" +#include "utils/image_io.h" +// clang-format on + +#define INPUT_IMAGE "./images/test_image.jpg" + +// Checking that parallel modes get the result as sequential +#define TEST_CONVOL(convol_mode) \ + image_t *image = ctx->input_image; \ + filter_t *filter = ctx->filter; \ + ctx->seq_result = seq_convolution(image, filter); \ + ctx->parallel_result = convol_mode(image, filter); \ + assert_images_equal(ctx->seq_result, ctx->parallel_result); + +typedef struct { + image_t *input_image; + filter_t *filter; + image_t *seq_result; + image_t *parallel_result; +} state_t; + +static void assert_images_equal(image_t *expected, image_t *actual) { + assert_non_null(expected); + assert_non_null(actual); + + assert_int_equal(expected->width, actual->width); + assert_int_equal(expected->height, actual->height); + assert_int_equal(expected->channels, actual->channels); + + int size = expected->width * expected->height * expected->channels; + + for (int i = 0; i < size; i++) { + assert_int_equal(expected->image_data[i], actual->image_data[i]); + } +} + +static int setup(void **state) { + state_t *ctx = malloc(sizeof(state_t)); + if (!ctx) { + return -1; + } + + ctx->input_image = load_image(INPUT_IMAGE); + if (!ctx->input_image) { + free(ctx); + return -1; + } + ctx->filter = create_filter(MOTION_BLUR); + if (!ctx->filter) { + free_image(ctx->input_image); + free(ctx); + return -1; + } + ctx->seq_result = NULL; + ctx->parallel_result = NULL; + *state = ctx; + return 0; +} + +static int teardown(void **state) { + state_t *ctx = *state; + if (ctx) { + free_filter(ctx->filter); + free_image(ctx->input_image); + free_image(ctx->seq_result); + free_image(ctx->parallel_result); + free(ctx); + } + return 0; +} + +static void test_pixel_convolution(void **state) { + state_t *ctx = *state; + TEST_CONVOL(parallel_pixel_convolution); +} + +static void test_row_convolution(void **state) { + state_t *ctx = *state; + TEST_CONVOL(parallel_row_convolution); +} + +static void test_column_convolution(void **state) { + state_t *ctx = *state; + TEST_CONVOL(parallel_column_convolution); +} + +static void test_block_convolution(void **state) { + state_t *ctx = *state; + TEST_CONVOL(parallel_block_convolution); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_pixel_convolution, setup, teardown), + cmocka_unit_test_setup_teardown(test_row_convolution, setup, teardown), + cmocka_unit_test_setup_teardown(test_column_convolution, setup, teardown), + cmocka_unit_test_setup_teardown(test_block_convolution, setup, teardown), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} From 18090601c27da502c268dbc8eb65f8878f4d888b Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 23:18:06 +0300 Subject: [PATCH 10/11] build: update Makefile --- Makefile | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 16ed060..34eec26 100644 --- a/Makefile +++ b/Makefile @@ -8,20 +8,26 @@ LDFLAGS_ASAN := -fsanitize=address CFLAGS := $(CFLAGS_COMMON) $(CFLAGS_DEBUG) CFLAGS_BENCH := $(CFLAGS_COMMON) $(CFLAGS_RELEASE) -DNDEBUG -LDFLAGS := -lm +LDFLAGS := -lm -fopenmp -SRC := $(shell find src -name '*.c' ! -name 'main.c' ) +SRC := $(shell find src -name '*.c' ! -name 'main.c' ! -name 'benchmark.c') APP_SRC := $(SRC) src/main.c - +BENCH_SRC := $(SRC) src/benchmark.c HDR := $(shell find src -name '*.h') $(shell find tests -name '*.h' 2>/dev/null || true) TARGET := build/convol +BENCH_TARGET := build/benchmark + +TEST_SRC := $(shell find tests -name '*.c' 2>/dev/null || true) +TEST_BIN := build/tests -.PHONY: build clean fmt help asan +.PHONY: build clean fmt test bench help asan help: @echo "Available targets:" @echo " build - Build main program" + @echo " test - Run tests" + @echo " bench - Run single image benchmark" @echo " asan - Build with AddressSanitizer" @echo " clean - Remove build directory" @echo " fmt - Format code" @@ -32,6 +38,20 @@ $(TARGET): $(APP_SRC) $(HDR) @mkdir -p build $(CC) $(CFLAGS) $(APP_SRC) -o $@ $(LDFLAGS) +$(BENCH_TARGET): $(BENCH_SRC) $(HDR) + @mkdir -p build + $(CC) $(CFLAGS_BENCH) $(BENCH_SRC) -o $@ $(LDFLAGS) + +$(TEST_BIN): $(SRC) $(TEST_SRC) $(HDR) + @mkdir -p build + $(CC) $(CFLAGS) $(SRC) $(TEST_SRC) -o $@ $(LDFLAGS) -lcmocka + +bench: $(BENCH_TARGET) + @./$(BENCH_TARGET) $(FILTER) $(IMAGE) + +test: $(TEST_BIN) + @./$(TEST_BIN) + asan: clean @mkdir -p build $(CC) $(CFLAGS) $(CFLAGS_ASAN) $(APP_SRC) -o $(TARGET)_asan $(LDFLAGS) $(LDFLAGS_ASAN) @@ -40,4 +60,8 @@ clean: rm -rf build fmt: - clang-format -i $(SRC) $(APP_SRC) $(HDR) + clang-format -i $(SRC) $(APP_SRC) $(HDR) $(TEST_SRC) $(BENCH_SRC) + +# Default values for benchmark +FILTER ?= motion +IMAGE ?= ./images/test_image.jpg From 9eaaf7ce1e5ab35f92e8a3270deedb586e0c6e2a Mon Sep 17 00:00:00 2001 From: Tenyaeva Ekaterina Date: Fri, 15 May 2026 23:21:14 +0300 Subject: [PATCH 11/11] docs: update README --- README.md | 33 ++++++++++++++- benchmark_res/README.md | 51 ++++++++++++++++++++++++ benchmark_res/result_large.png | Bin 0 -> 110141 bytes benchmark_res/result_large_parallel.png | Bin 0 -> 172894 bytes benchmark_res/result_small.png | Bin 0 -> 106879 bytes benchmark_res/result_small_parallel.png | Bin 0 -> 118617 bytes 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 benchmark_res/README.md create mode 100644 benchmark_res/result_large.png create mode 100644 benchmark_res/result_large_parallel.png create mode 100644 benchmark_res/result_small.png create mode 100644 benchmark_res/result_small_parallel.png diff --git a/README.md b/README.md index 917e8b8..887874b 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ Image convolution tool with multiple parallelization strategies. - **Filters**: `blur`, `sharpen`, `gaussian`, `motion`, `edge`, `emboss` - **Modes**: - `seq` - sequential + - `row` - parallel by rows + - `column` - parallel by columns + - `pixel` - parallel by individual pixels + - `block` - parallel by blocks (64x64) - **Formats**: `jpeg`, `jpg`, `png`, `bmp`, `tga` ## Build @@ -26,4 +30,31 @@ make build ```bash # Sequential blur on an image ./build/convol image.jpg --filter=blur --mode=seq -`` + +# Parallel by blocks with motion blur +./build/convol image.png --filter=motion --mode=block + +# Emboss effect with row-parallel execution +./build/convol photo.jpg --filter=emboss --mode=row + +# Parallel blocks with motion blur for multiple files +./build/convol image.png photo.png file.bmp --filter=motion --mode=block +``` + +## Tests + +``` +make test +``` +## Benchmarks + +**Single image benchmark (comparison of modes)** +```bash +# Default (filter=motion, image=./images/test_image.jpg) +make bench +# Custom filter and image +make bench FILTER=blur IMAGE=./images/photo.png +make bench FILTER=gaussian IMAGE=./images/image.jpg +``` + +Benchmark results are located in a [corresponding](./benchmark_res/) folder \ No newline at end of file diff --git a/benchmark_res/README.md b/benchmark_res/README.md new file mode 100644 index 0000000..cafb8e2 --- /dev/null +++ b/benchmark_res/README.md @@ -0,0 +1,51 @@ +# Benchmark Results + +**Benchmark Setup**: +- Ubuntu 25.04 +- AMD Ryzen 5 4600H @ 3.0 GHz (12 threads) +- 32 GB DDR4 +- GCC 15.0.1 + +## Small Image + +**Configuration:** +- Filter: motion (9x9) +- Image: 736x469, 3 channels +- Runs: 100 + +| Mode | Avg (sec) | Min (sec) | Median (sec) | Max (sec) | +|--------|-----------|-----------|--------------|-----------| +| seq | 0.109843 | 0.109399 | 0.109727 | 0.122655 | +| row | 0.018749 | 0.018467 | 0.018488 | 0.028643 | +| pixel | **0.018463** | **0.018279** | **0.018302** | **0.024248** | +| column | 0.018745 | 0.018511 | 0.018550 | 0.024789 | +| block | 0.021096 | 0.020226 | 0.020857 | 0.026649 | + +![Image Benchmark](result_small.png) +![Image Benchmark](result_small_parallel.png) + +## Large Image + +**Configuration:** +- Filter: motion (9x9) +- Image: 6000x4000, 3 channels +- Runs: 50 + +| Mode | Avg (sec) | Min (sec) | Median (sec) | Max (sec) | +|--------|-----------|-----------|--------------|-----------| +| seq | 7.683813 | 7.657912 | 7.680730 | 7.739433 | +| row | 1.295177 | 1.274591 | 1.284864 | 1.405707 | +| pixel | **1.291997** | **1.272699** | **1.283954** | **1.356831** | +| column | 1.475161 | 1.399772 | 1.447077 | 1.684282 | +| block | 1.310514 | 1.281334 | 1.301490 | 1.436669 | + +![Image Benchmark](result_large.png) +![Image Benchmark](result_large_parallel.png) + +## Conclusion + +We can make following conclusions: +- **Pixel mode achieves the best performance** +- **Row-parallel and Pixel-parallel are nearly identical** +- **Column mode** is the slowest due to poor cache locality +- **Block-parallel has higher overhead** on small images, but performs well on large images \ No newline at end of file diff --git a/benchmark_res/result_large.png b/benchmark_res/result_large.png new file mode 100644 index 0000000000000000000000000000000000000000..9bc0a49dfcb082d7a3e684bc0d627338232b6290 GIT binary patch literal 110141 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 BE}8%U literal 0 HcmV?d00001 diff --git a/benchmark_res/result_large_parallel.png b/benchmark_res/result_large_parallel.png new file mode 100644 index 0000000000000000000000000000000000000000..96dffca5bc68d4314eaadc60afcc2c9098fc44df GIT binary patch literal 172894 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

? zC;@K*qL10DsCjIlED5|mj?maVsPDsl-Ym0umzFA`DJ~-f`XANL4aK;?*}z7`+!4px zwpx^XQD=?8G`yXxIx)xd{jX+U*^Yz@dj)`A7fPWGY}ZehMdevJq`az--G%q2DK=pV zO=w<0$J-VwR7wDqfn@XeB~Ub636>Fhj%NM`0*MTdX%Yxmf(cX3Z}tRDLwlh`N^W8A zu9aR_(t18lgVlh+hT+(HFT-3Ek=S2kKdgGBx_8U0KM|=P7L+Y(8&H(d>PSFXQF031 z*S$9l2nOH}UM2yJIWNKLs)WCNoCSUl?6#=iZo49#PuGOgd|Q@XG4gvSPY$R2_ALjq zYO#la-vEaX3jO2Q8_p^!qFb1g9VE>BxrL43sd3R7hxz;{kO4i~2jUyz&IRIwb8uPJQ9n%q!$!=HQ8ulMOlz2WW!NoMDK# z%oKoQF;ZRf0tf4KhC;|6fDq+$q->HL#sC{-Ne&9I#{gbsF;W{fRRuVVx)V|hU{ZM2 zMXpN_h-+wQye}^YxQH$8i32y^EiFa-;xSId7YLTX&7YYHmgxi#5jyz=+>&K_0*cHa0!EF})GU5#g!f47>UrQB5VGl}H(mOUimA zZrG35|58#?IN2aAxIv^1gjg>s)SoyRhy1G@^?f0 zh-qb~b#(z5MbH_|5z%SXVgX*oH#QtVe?Uo;bZfK-JEB(oIzxW1>_zGNqe(!_y2A>1 zKlSqwQ>V=RX3SM1Upif9>mM)j$gC+q4?~95gWYl@Sg!h_^q7^W{9vss&v(Zu*=6dNeCESb^u6C z>=8z1AFif!9x;bftPU7C$KNIiQilfq@ihuw(KiqHYhr|vArA!mk@Ihmxdj{Q9^2gEn#4F7uWXZXS-hZs-dHyuW$HE&|r*u z&p6F_KcE*SLEG#)>aW5;eQ30Jnw;GKd}TAm7i{uYEQPIfxmK^ZUjJCm;xINH9*{BSex(lxj($ji4%R;OkyENs?ry*g}kKYp;V-sd+TgbpR#U-zcqonSfW^aEbP5 z12vGf;cHU*aDRHVeoQzS_ggC0GkMsBHi6^PXo>|Bwp|w(0w~kCOD?yn9)F*SE3h^h zdL5zDuH!>-`p9yh*@zT5$X?rH`!Z|;6ihKm%NfJN9`-XC$kc(1$-@o6vZ9a*|JG<> z7w7f22s_YLT)m~m2&ornw?J_|gFX5s13lvn=lQQofKSkc3CW~h(>HUtM$VsU;Sw+E zr=XuVpB~4|ieDVSOX@7`R~qmeG|i1BF*K4lQkXX|5ZU5s+wJBYzj#div_+M1Jl0sB zMCGIkLS_ihf$?%^-M|X=#$rF=lqmn5Wi-F_c$DGKyo1Ye)&@H;bTl?8$*$@ETh$&h zF2|J#;#a~h+&nC3^)V6aO7qF95ZsJc^$-ktSRxzgQkagwX-~jI2xlbZbH|kz z6%gN+p}z$8BDc4%A;=@VN{#8C2wZjsn|*ACAs3&)c3q-lG6pR64RjR5rldrY0bz2C zMw&?;QK}@RR#G>7EM0&}s#qO-hly>&Jyd_SxifJ$*7{p&?CYILVS^_`3v07HfTsc2 zKpZFrlFgZo#Ga7iOq>x=*OVu8ol%d%s-9a2VeWhN+Bf4*xDO!0E=up+Gz`gU@=B7< z*1ZmQPlpA09W7_mcC@=7x+!s%+fIWnjWDVzAduzQccFR76z$%9#+)zL3kA{b@{`hT+Bv7UO+xyyMuo!8}O&k0Acm;`oMqN4o{gMvHpC zHM5`uWqP0#vr*l|J}6Mz5nY>(%(bCe03|3eMP{k=dJ-u#bWu+D@ae8M@b6GU#(6YXRgV7k$sNEZi zej5tSQg+(y+8LUx#Of)kjRu~p5-!$n z56(uN`xR^h=>xhFLhH-X`yW5TXPPjb==L za7W-p*1(6Sz|n4FGMZ%*Z2B(z-e}SHex?u{Ac|++&n1s2bUv*0s6YEw>Qj4dmgfV)5K$iPR5s9& z>#JTi=Spthg_KhRCO*}0IWZF0HU_d{>)31k(kE|edp}dF%4&Z}VeA4_Juxz^aIc4V zkFDLpDrUEioiwwtj=Hn=&W-K3wPZnNqx5W-+$+PK7=t|o0b|CVu;M=J;Z}M8?9ALm z00r=HB%>VR*_8AmW=0D`9QrW1QO36xJ3x+H9?9T~8~vGLRpDXdZ+mrjBIFl0+1c}O z#atVu;KDbUl*uRGhv73?gFRVtvhBWrJdnrYe}{+Y!}f#4&V9;3QuQZY^GpUyO&a;- zdb1yEHz@8oibz%7PQ|^sKJSjObnBBdsmHHcwJpxYNZ_YvZurn zu88(;wndsq;$BAwyRz&%@96Y03&{ZQSFj*)6}3iLcJB*QNlql!a1Zey8PK9_%Pyzf zu->|gsqNn1dHloZ2`rVa0;#uBT@QMay+sB7^!X4P?G$3WPVWt%7m{f_D8^|J20c1UaE`kp3jJZ%bf=qkH$ zDrg%fWnGLNUIYB8(iqx+yr(Dc=DY;(6#=@aV#oF^Q{j!xX1n;ugvCn?Ryg;Y=-4}; zmQU}ucUCU)TD)q)5?=!xUzA$P5N?BQ@V%6%@#z<(L|WBz!?l|UeETy2qc|H zNjzUF;S_=uHIRtfKqFmUnP|SN#YzLwCb9|8N&$mynT4bo-U?OG(W>U~a}`rOE={}j z>4GKD3uobV`Y{sIl&gS5vg*Cv14NdBXUgV$G_u&~#rQ5aC>%e*23-+9L{9pOT)HFe z8*CBJaZ#7Kl5P`sgU_0MLIpuBl4ru7s66mD(-F}HK)Tn2j*pto*-1_VwY<%|Lz&L2 zkZ0s6`}2yci=LNW}O&}`jE%5QIP-_10J z8es!s7jmYZ>U-$@sdTAeKN1Mg+D>I@xmX;L+3~pn*p(u}u=6r(N4Q8dVGAyq9k^8fwb^O%lZ{h2P)7ldxB~5>2R4~hNjEH{ zKB+$2%=%X+Z)4yad7+6$qg$ z)*vHuROs6;WlR+L89}&lehCq*`4J(yx_uSfMdk>{7oU|Y@egn|OoZLw7q}0Q^?=&k za~8HUV6n zGEtxxJVgQvJJ8i-X?4Cjb=x@BoO@Kew!u=}xpN2QLbONw)QZC{!44F-^6tV}q+|qc z;4jOF1PT&T;9CX`6Ek{8T4~4~5P2mOMUepjwPW#GcQ#vO&&<1s-L9YY`y8d?QA9q}mMrWv=kIt>e2M-G3iapdzS#fnafNro(B>lhKGz)jcZf>b+ef@f!Gs$5#j=K-`&@OUUoZ>qjO z!hIquG1qNp&~HLY9~+mfSa2=C#yDfgh(I5C>X-i^PChy`Qo|$9JEpL!ag3AawEvGN z*3ZvN)i$6Ocpvqj>4C9oZ!~t(aSvU>KL^f6` z%=10)eJwBljL}_Qf+7ZBZ`8pwg;0G}8Jf!Yehz&hWb$L-l%jAw+iQOwJnw&!S~M;l z^KYL|YY-TFU=O3}`u_cG>}fQVqCA1}z>1tFPZJVWWtk!0#<4`P&q5LfCxBBb;knO2 ztg@`~Ve^;x{!(@S#l8HKsghwo!c!rySaXecQGk>+_A{VFeZ@Sq$BkM6lqAPgceG}; z4ShcV)0WJ+Lh?yaPLOI+Fx_rsmB@oZmqKpoUhB_1crJ0IF$EvQ@y9pvk-6KTGX948 z`hU{~j!?qLb^pIIv;Y4`{Ez0NM3p$X{6{gUd$HCDc$P^0|F^ zzZ-;I{}0+nMg@4`a=rt?V|Z7X9Btr^2_~q-u==tQEsZ7RRN2qFNGccja*=?){-K=$ z;jO~T4o&zH3d2Egg@_xo5aFM}2L-zGQjL~7%2dQ1j7MMy@Q2x2>7}O*BH%5<+a?xK zhPTNd_0)mu`*~-vRT+GL^2z_b$3SSxHwz?g@H2ksr4$A-7g%`6kfaNw>ipO^CXcY( zfRe_5yu4%za5S{9=)CW!wM2y-79Cz4t}LQN@~0nPPbY=bd6({aW`DZ!5-9}e1>kjp z@m<7z?%MbLmS6sFPV2k%G6#t8lhYcR3V?-f$o&satNP=&n9appb=5prXLLoOJdOf( zsW>Rl#f>OZBb-5Eb0BcFsoD2EC}GaM3-%O#8FoCXnddZjnI+OFkn6$EL?jO%mmvNv z@H;vKb#w&ufIg7Am8NdSqKs)LVCdh^m^jAKE*T{Tfn0?eRJs}IVPI(#pxQ)f6tq>1 ziJ)dtJj}JE4igy(LJ|%SI7ul_`H|L;sOXWZSA#97G$Z+GsfgF(e7R6(oQTf-1{o^g z#WH2gWl?%iazXTj-BSoXMg(Jch1^*;FhlPAX6y%W?wF2vhCLyo)8ufrY;~rZwtjy| zcR@kHla7vB2(nNd2WpLo2Y742mkEeqfMbtoqPIbjlAHs4<@zDaL&FfJ@qqA`d;2yj zl@qr>4hxkwRJ~A2+!F#p;FM*vlXz&mzJJ;b@VCI!F@)d3t)YyH{UgmI02rUg0~{BM zJF(_ln>OlO`K%PSBXE-Gy}x*;vOfJkdY2J86{7ydlBbShi1}y;e*c_AoBMY=wi+Ew z|C=5AGEQmkw&Kc>_#jPu4qo{%q1LZpK>i~r!FL->I^dnI(3zh-)0XY?3 z1eV>JQB{JF1njE(eo>db=V-`es4t~+%}IFY-=G1oF#*_!0{hX0E+xCTc9xf^-`X`C`QKLAQL3ADL)p}dGxIwTspO_0`uNC|4I zi0=^*p%cWSA%C&mc^dzAqV(WmzU9Df+)S>Qmuyg6g%N16mC4r1xAams4%pnL3>xIP zi}935v{}r7n&r3e`o0FjtAi*EF~qdL5tW%OBS6 za7z6a3>wTD7Em%kwp0_z2mXk<7HZ24wl^DcyhZxdRHWeOn8R|g=rV-7f-D*t zp;xhk>|lr7Fq&CNSyEx8vY0R-JKO`e6gA;1FWIVCg19zeta9}bke8r7%p;8&9!wvO z$6un9M^9S)V8jLR;;JiYUH}$`l=N`rQ$@Ok#;3Z^)|FnhWhI~7Z`$6&cj|202taySZ9_Zq?W1$YGRHzH2Z;&6dmdX1Q59f)=)fvnKge7JF?3k|km z@1G8!g6yfESEO7No!=o1oE|u`jkMDjGa9RPBJ3m*QK&EYkvezK@IV6!+qfzc0#e3- zpc~5YmV8nqVTD3LTK<;OJU@yl^-6R5+ieyQ^8zv@q!}(mGkZGTUp1~q2h!>PH)=qdsi9Z+N3BH z2VsiOCUPeSoSRFzzKknCEP-N?wh|OJLCaAI2UQz==@YkzXw0{M+ng!F4txf0?>k4* zxl7GC1lV6u*?rampAz+xjyYY6_g0`EgZjf&oUxd4hh}Z0Ng(@yX$h}|TIk%oX*AZO zZW+@*c?%00)VreyEDL)2Vq+F{a`l31I0B$OQ=oe6$iv}97YIg5TnX-oDJSZE-}>`v zA72>lF#xZC>M<~#N?Cc+z)SIYfQztdliGbp#9VPs zGvtxOV+?Sn2+A=^Vx@&0ji_IDZW?+?-}j9U`(svjL7kEEtxuu#W7D=d$ayFcy?K1{0I-qwjRdaYS^{mdBi($a zkH0ZIk3a5t?tKd7I5=#a8|1!VM-*(hBSvw$VDS-C6Otj0(fTaz4X%PdIjnVg4EOgV zMY^N3Hsy2gTQlylT#1O{#*^08OuxG?5QoO7gEN91fPM6QX7x?V<5h3RW&~}J^HPB; zm$C-hP@9vmJODVZY(HK)Yj8JsYMhtAqNY@Y=e$i?>%4jN(;TwQv! zot*}H9s@ghz@L7Y>kr-QBo%fzP*Mcyl{;Zx0 zn0-($V4YA70WuE=4ZMgirzTY`W!=bbgsFp`HuEl~kWK?QMidMPrxWG02sAGE@4exgQAOb3S#`k$#Cms?>Fl+8 z(yS}aP0R#Rdh8F+z>8~ej1Z53&=zMj_|+#Jig6Eif~iJR;sYZb%?K!MV=sbvgZ&Cd zGwi;<_lsY|fHo^9*0bUnCFs%psT#3*6jM(>+od5Hpo+F3Kyqjv?y^HCqZ0&~#$zYL zgoB+=O6uUq26^X$n-OPp+S(f8;>tfpD{WValkr1fnY*L-Yp|#~z%Efg2+ZW~d8M*) znmEtM5>PGCNc~9Xe{&Mhzi8 zl=7ygk_b_DUDdPbC;ndBk4!?kmhm`1t@tZMVC?fif?F~r&_3_Tqn*JP)xINEirU(0 zz;epZHL=h9a=t?z*)}dbr z(bR=!N8_3wlr^WCmdPW8iLa39(&Eq1qX2G~x!;-^36BeX^=P{h*mfNa4+tJ$Up}Kl z4%iLpl0`@(+xy8&?N%XBps~a+1g+%saQFaHcVXrx8y`u-mOT|qe0EGsaEzyNEC$RS)CRNx0HjjteTa*=6gP~5z&J~MhL)Cx2wx8xQt;kzN#M+)`X3hL z^bo#P9^&E2$e*9GVbINZkJ_OK%KT3)!=L5i%Ir;Q@1EVF#U@7pQ(fR7siI z_;}Jw++WE6Ym&U|IHUBE(?@QFpaccpO+iOhNgavC_dq$WUgq`GPZyiCZKH*Uah;6hqEoT(34jnFim=z-DP;zB-6q!NUvKc8#t%I` z$!;=9UW6St^`f@@fd2~oetji&CCEVe_FN_>qU9`$A`~!H!K5e{rbi6fL81(^D+fK2;?t-_66Y9WU0$2{t8eSrG<(81^kuM41!{TLUK6ocnn}C$ zZUQ3c>IfRvbRKGOjzXaDdR8^liNPf7CiH(&MYYyu(k%?CoYP>LvsRG9SM&_I_}JLy zl5{*}+cy^pJ8N&>@3!dvysP-Fgq%xq;r%OoEc!JU6k5TWT|{dNq}W zBkmi+f8MMc0 z-m&m-^%+DtHql^B=H)3O7e$PQ7v5!;Y7lo1QN)ZgXkh2kSNLxM@2O-nW1Cf{k|^PqCRf0H@^_OP z2jr)LYX!_wtvzBaSiOCs=eQs ztD`_=TH7&n&!RiDfM+9&?RSZp*SfSfjh*{IP=rqaKfmZq$~QRz8)+rwmAJB|jfu*n z?vwl$vnCK4)#~xnxZ(d@m_KzI9iFD9KC(-Vg7L%}p`v|x{wv%T7 zog|u0DQchZku=}m-N*Z!qa>}jg+65T?PfmO2L6B&h$H$&3<`V@4M!c)JUeMA9IW3@ zS)}Z9PG;)n`-Q85HqrPqoL18q-ebVgp#HyFe<5Jv(%W&LXU{H0PMvNiySLlIf8BA5 zgWiw%eHr#Y()(d-(1(L~)omxCtoiDM6>bAd0?jYEuXTwtp|wQ;y0nQ_SUDHan!HJ6 ze{F?({><|T346e%cd=z!%nTvqN}fHLHKwK85Rzg!tpPV>*stJnlbx&S|9A10*ZYl> zXbF*3J7$JZep1Ocl>8h`8qj5R>hbRuS-kKEbBvyYTzs=q3XJDT=}bsMII+Y9X3Xr{M*G^wNd70|^(#Qjaef>uA7+6!&6 ztV-5syhvJrrcRWdMiZiu8wfxV5zj!$)}Yy0!_k-HA6C^xV#~}Gc)S$h|Fvhz)yl<| z+Phu_4Tzc0Uqs5**#C8Pb(^Mc`A0Lo3-fur{VK4YbUk)ZAC)Wc6Ig;?DTUvR(Ef>~ z!cJ|m!euS{yIbbUEFW(JGBCC_7#zlxNg?1qD3D@9Su+9vB48X=EPUn*M$u9T9yEBq zcqV#^!q#A9jB3+($s56ok(Rt1v~1Aiz-WfyM@|w9*S43>ZN*CC1frY$>H7hV3XR2icgw5`F`m?c-uC zk+`~QXynvAQ3;=?p)oEce&pKd`5lW+HpGTJf$Y&rFYp2oIsd?%-=;k4s1kKp5ahsI z8I*qb@_Brs$)-)~6}{^9X;t>DwbC0)8t8gikl=~x0q_v=#$#fZV`rhw?CH}^cZ2EG zisX8X|BP4f3!Ru@@4>SN8!q9GAI#M$pO{X*34m3`BAN9-o?NCitaC`ZItp7X-snQ0zxZ7I%(j!K??a%-|bUm?(3r>kgF~Q@QvUnQL_{< zG2w=}V#IeEJ1yZR>t$avMuIqnZB!M>iKupF@dqw)@j}H!Bp$~Bi38FHDla7sW58Bb$vP@_hQah=0sfh*d^aH*bI70=U5#UBwfBJI^?WoXC7+mh{hO|hYuwQih zfTPm+M>MgPh@hmtw|PCg@)Cv$2?g4(c|3xO*vI*kH=8(icY%@u-P)_CsQrZ+92Q2u z4)U4gD{xHNs(bz5PWsO8Otu5ATWdfTsU~%(+z<$vgANT+Gy=m?OL0WnKPik+*WT@r5M3BZ2P&-mP0mFE)z71?hsU6xowOR;KyaZTsVB`N_d=b-)-;!#m1C1g zN?H0>^up-fpByBoLlX{T!%($FTPC_g)FH`xo;ypzM`BzD2}nL5cY@zR{T+}(mhnZN zOZQMxK`~XK_`z=kQ>U>yYgq|p9^0ick)>1AxJ;CfCW-+<+%ij=;|-Fw#3?6TI(Cxh z_=m6qP|Go-$-}+W#c5SnM;R%(2_vEV1<0twe?Fh1#cH6Lqh%9~*xq;Vn3O92wp%LX zWkA~}f(prNsEcLn_}7qJ@%?`c$qlZiD%0wT9`{%Yy4p*hDbkUBT>o;4aYTKJ=HYLl z`HxLy2r2UxoCDpO6cJ#cy!lYigIFmDX2C1}(Tm8ibL#LN*8S z{mtwX5J_v%?V3e}VBk^zk}xMcn1Yf4$_~He9#Col=0s!(_#gr`;Der|@wq^5SQ9Db zKJ=nfa)o82x2v}y2ynt)PpB?{RlM14FZINx_dxpoR^B6RuWmUPG1L1;n%$O}a3)4$ z_1I%3>7a}(e5Q@H%TKl;;l-Db>(1bH8WWO|lKNC-R6_WdqNU(1Kp*hu;Xlz2R8@H9 zTrXt|SgxGKrG-?F1Nd@N*pR`aP5_0n(d=>lmA|q{{~*#FO{~zbDSJ2fgkV*%_3O&n zIzUv&a7Fd~*BWjpQ=tWT*p}jaxa`%1@W`m%j4o3g?G}iOSi&GG5hX-5XLZ2>UpZuL zLflzqJ#vQBt(Z2ViT4Lf7SoPW;Oe|tz9w%kvtB6ZBxoAtOSNQpm`F*=LHsDIc5cD6 zgefp6tgoX=GK;Ageh*Z++EZMvv1*#+AL}9E28bI?T#$6xu4@~(X^}AHiO%)n0FL~= z`6@~>1-J)Zq3bc5NHeG$j4Ijz9S@T}a8wq%lJ%9rjU*BwIdEf^M&%D)gg?s+nZq|N zb66q?gc4X+^k(1AtJh$%{dRsc)e->CDQae^cdoFRj|lDH`t=8YK3=omHm>B4`c2ESnHW(%Lj z&)P742#mX>Q%P51Ln9@*_M$_q>NGYP=_5ut;8#tyXXB0=LG0sSgMIw2sWFgQG@7oj z*zfoj+E-E!6^l>o+OULmujBq9Z>w`SMx2E@oLW#eMvyANo7`~1TX@7jE{l?mRQS`UOsk=8;_yOHkVa;|QH-`Y$HXs?R(fW3c|6k1(QSuu=Oh zKl;f&8OZf7bo}a~i#n}oxP$$R?XxBnlst1Ny!snJP2jGi6^MHV+TQwJj^g35ED4F7 z!4wO~Wp9n1<5zdth~Hlv2Z-C5J>LBaEKNxJ{rPiIB00vH?|uxo=MPoTe`pn;6o*V2 zweP@&$9KT_r*XWG==-#IEf)@W_`$2Pwi)YiP7~&7#~r^7laR;6aod@WGS{3+ZhxR+cLPo0|`T zRXB7H&>v1`1T_%g3bD_qTGl_(0J6Edm4cN6Srmq~-4oiRv8y=VUsF{$xCUx+em+s6 zvPahK|0Rh+(-_&%mRY-tG?+s@alsuImiTUPCAf~z{jmN|Xjjx_W-pp?IY!o&76>T0 zdaEuLGB^GgL05ie@@KEIQG#|t57{9nBYkNuy<;R~{)u$p?&AVmy?h9HfIqsd8IC6Q z$RolYYbWde*Wq>JXdThuCy6QkCu@p3u0HdIe z?7t34{*67||8B)hI4~F6%|X)DUsx!QCS7~ojXfdmG7AJ&(yA*7>Ez!fY|-6<@9d~wa)%<80%by>1z-r79ZmDK{{`ILrYR2A5RRk)PVa&VsjK@wjWfAK zVuTksUkNrWlNpQ-X+$pldf+SlItep6Ry;N`dGQ zEE}-U^!-!5;=lKVY{gT}|Gq)H9?mx%kq=zFeoQa4PQsoURWgG+9US4Mss|JlCZ<7KnHP|=7t?6qT?RJW{hAiC5!}5Dc(@>K&T1;9qn3Zi2#;^ zX515^63r%?&>;J3@tqLIuOO;-@^wP!Zq(elLL65+@%YCb0!zrDLGzGW28nk#{>fPr z9^hWa@-DKMF`AG-U6iO!-`@UDNYUkq_W-JaO|C$~s}u{#!J_$dM`5YIj(3J?J2kib4K{UsY)_Y{xcKxvF^F zEB+t{^1=zSt;r<}OSr~6FhZt)m~a`!@rm4w9DI_m8rU<)Fwo(KnhK<2Q1x;YqLo94 z4uJ^BL?9(e+P}m{A>@H#2R1wyxTG3fzX3?ASl=hz3g{3+Xt^ghdTxRs`LH!OoP}fB z>#I(__`A?{48*E>gqAVQ!G7Y0=I0(^si!7F?~f*80^d%g(g;Es)eLuorN!XJhKI_? z?I@K#ft)9usSHPxxaHs|`{wW+@aPL_{5x32SOhRacV-ZM52 zd~~02^ki&gk3R9}?h3Ww)>6UC+)t9!U$i#mC+VqbFJHe*w6$SrglFZKrbXp>X>H7L zT#q0yV{%-Q?)czn~__!G`R40 z$X}*zyEyB7V{CkJ;~V4n$AZ_+CJwlDFBho3IBV;arGIzin{iVT1)cql?j9cM+S>IW z63st#^xF4TmB%T@9(mCrEg3K)Pu~k%C={z~Yuz^eWpwBG-hvkFQJ3unuFLJj}0mR4%R1$waOd{f-z#aSP1tqkbN*cK3_u(a$7 zT-ji)GS3y4HL8F}=vh z_U%x_2MK5EroK3S1DYdQnkhCnjz5NAqGpB4?Xw*JoF8em;j^ZD~<^_jKj?ytH%SZq0XW6$^*m$wy( z?Z9X=@7G@%!rYcm&-5L%CyZpXuBH+L8FoC&)+y~10=iSBq@_XXZ|dq>F4z53%`m3? z)924qa-MLqPm1Z+QY_YfXRotVd%_&r?5!!LJU3&HRcx$n_f?J9kxmbzGuHblh_GJ( zZUSSGjkt*e_{qx%Unxl~(;6aspS6%EG@}&Jf>!YjL5%Uf- zs~^6#VVaXoAlbM$?chv`Vy{I2Ug|K~cL>pZ7vfA{zES?gZ+eXq5)cyE;IL+jp;g=^^=uVFjb z^((Rg(b{onxS+t|gRu#&>x3us5^K@`i% zD){mRv3;W?KOfE;DsA`p&9AV9;FIT>gV)g+DH@^}el$kgo12zGC#s>RhX&#v%&FM! zxb;4LlmJIx$IuWBFUWpLl?m$x-ShP}LAi4ne3Yvx8*}hcIGq(M9TH3zE=bK8Nvg%6 zkKVk&gng>(mpjKDD4flJauG?%;tfn0b7n@yrDXjwh_KR)g0Q3;MbdVdO|bH<^Ebvd z$B;SQZ=W7P%FS(^fY{FbUn1()QagPAzyJw4*2RcEymd-PPw&Y=m>65j!^$jrjb(;^}e?1OT5geqN8WPw!QBWXT zs5dq2I9h48jcbG1BA&?6N;n8X9Ex3tlQ_fxEKTh;|6EkmI6gjZ+-^*^JauTJ}GRs0}l-bz**J9zjx#$*7j&~`s-N#SP+JVG&O9(XB7Z+?Zh1J2X7e_oudq*6v~JA^vz z?1u62ix3IH+S9Tt~zaC!$n9{aCLbjDPV3^bpzZNgU*%JwmBSW zJe>N{(%1k0`L_z!Cm%rfig8fUSUx zA6VO;LTx_khzs8*jx1gL(Fe&J9)Ux#_HtfDEj&i0VW?$s>+`(IMp*8uqpRzjW&_st zg5qLqC~C*pW227cE)_Lfy;5rLv!7-B&}&~`@JYm*C8I-+gzhMbca0}2nG@^~g^Qo2 z&)@0wJ>%6(dwaX??_1hAB$YP?5UpERevToFHAB6HM((tvWsBu%v zoleBJYikdccKX{e`LmMgJOY~t#Dix_5PD#3SIoVPTjj%z1)q*z6RL*wS&liL5-0D? zm30gaF+oQcM&nf+dZ|N#a0e%U03nu!!21oZ-_Nj}3YL+BS=h|<&R|h6{LbBZBXxx6Wvqx}XVz7?uVwt{04hlcd_`O6m{G!hdRuN#$&{4tLn zvzJ?{d#c-LE&3FevKB3;z;u-Y>BS+uH;1AuW&qA7@k;Ae!eXI(FrfAVlf7B8V<< z$DR9sorKWQO?vYNy&q(*WVM*x9S@$}LcN8y=btSGKjr0}IZ6WVu8GJ8hR!orwGUEo z03JFgrYqM+CYGmKUszh&!q*CbCB#IRXpwGta!Ik)NfJG53BMI~B~`&&xU?d!av$0j z{3b-r*60QX2U9h9Awoj@2F6`iRg=xAig+1N-NhbBF21he%KOyN=wB?Q2XvMx>gpV`av3p4_JQr z%WkZLuu;zL1$Ze4ImbB>AU$ClL-`gYq>zx15~ro{ z`yN+)oP_QiR4E%S?d`xuz|G=&Q@2u4uFX5jqjDemMP8=_z)OUaVPfK|ky(#rK`G~G zgZKp~7J%)j)2bh}Yy~B}NgTq9b?kce=Ef@vihH~O`e!ZM?aAh$C{lL?nBacNxKt?d01ViHD;QFFRY+uMk+c~O)sIhC5 z-oW?rN8i%Y>Olal3D6LN)1lky^-$mwBkM&-wD!#k zX6-*)Z0E)Y^0h*0gzHNy2dN%D8DP^J>a-NThka$iKHIUpEDUVWZS_CF53C?Rw|*_) zgY(JPB^j$s<~5eg0#i4hAd#;Do3FM__rBBz59YNAuLyV|(AQOH! zS>D|F6n*^bqb(&Axj~`4%bbnoAU@7g(C!Xi#!Qq+dd?`|Ou{|?dl_|0OF}T*OUTd2+RaUw z`Y6;jkK=lmV4&=B@^)ZK0Q?Erz2hsLGI-U!N!1eTpI-0g_d-A^^;p9s0R{|^`1_)W z&jXw}5&zKpK~#r`5img?V`}*+H}}cl+9y8f&mhJd7iS_s!8>}Gedn8x&m}$y-7qo& z>d7TZDis`*H0xJ{$l8Q|y%?N^Zw~N2z@5$2JXA0m384YXgh@u;zs~|3+p*zu^*=Gp zfrs?XdsK+<+uusq4+k!K9+92{*( zCOc#xJd&hv0Mx^(4DE157Q~1$Aqw}sz34tI@qz#zfjau9brWFlBd*T0Z{#u~d3-iT zz^-1B`-ZR${|5wjKmlNh?rJN>X&lO^G1t<97d7;Wzu<4OJ5|qicM>dBs8?^C3TnA) zS2;Np@5ZHn3=BkPww-m5eNc0i)^8UUz0w?GQ>Xus%`5aFlj0S@XofKg`FLhaO80_p zl#rrqpxBXCLA9%--T{2}ncpuRS~j2$(J%0~;!GqVroP12IKDTmWbmCE^qCb-usHbs zPPlq~)NMrtTr(Tcg3 zaB6uW#qbm)FFN^*&*}YN6IaeLUR^t-7qmm((bUiq`zenLt#;3&LY}bg&l?61URUoX?X!6|W0-wK z-w*@$Xe>g-jNv>OxVEtS&)u(qrL{^uDHvk-pjCDIL#s+TIJPp|oqHmOlyQ^o*GJzO zGQ$NRgM0(o=ZaMwi+q1i$E6~{T8Wpn8)!Z-8Bo6V+?j6N7 zWYp;fq1@{=Nt9g<33};wRzA14$a+^;yftM=*rRSm$i z&f};t@ld*PF=2lKx-Q9WHAkcjTjF4Y>D4Pgv*&}l&2MMmVol7r1DBfyE@tSmMVXL1 zravaL^OGt)+8^pwuYd7Dep%VwWVOdIboo2k?#xU8P#lzXA2c!_4_?d4f>>Hb5Mes? zIt54>A`Ja48QN#)da}U_?o41)*BT1C0DNxpqrsM7x0~Kd- z%guH{sqBcqb_Vt-jap9BES3LL{Sn_tB>AdSI@_Kf_Jh=-hyQxV4@fD^xfJp-89Xu|}g$t%1w5CHM| zI7BdqA_RM2hl&R;0sC?NIu^258(dH@d!09VGgH=a9snq1h#sIi$(z*Fer&o??Qx0G zttKN*6DNs9HD7D(y8AJ25(uG*tS|F*Ab=yIHs5lPN12@V>v?+r0BBU~yayZ{T0C=- zsmO8tGhc*KUXBL;Ia7viWL!aId8i5fOkB%mx^oZZOUrBd%HDg{Z8nZycl6J;B4V^_ zG@5id(a0{ApqW!lExwWodts%|V(s3XTz(nCQsKfZN1_tn5enCzgM@lXiVM+{WAO4wxw>WV(%cs0%}C9=Ix!W-fXvm$f#fbGFUIi4;hECAVgoe zSSbm>BmT`q42R;OE`-IJ-C&XP-`W7Ptb>f}DC$F;H0T3hV_Vu*TYDIdTn2ke1P8e~ ztyK0cn!m76;w_rzflOtG^&~u;LVg&2{D;_=yer?CM2)>z(|Tu(7>{MQu6*DQ!t!5_ z_t!z!n9ry1Qk3Q1|9nNc?uI&>QVjy=b^li)X!UHhyeOWtCtkpFN?gzJgC)>{Cw<Gy?vrJVO&vrh>{!C~GDGAUmpLxeo*BghBzRYT4V9hM)v_@IK!;;*-EA z#>5wI-K0AqbU`~88=-QY+0M>x^rt!nWb<2ns{>cJ5Y)E6zLYvw8e-Sow|4iWNW$P7 zvKajO$K@36MxYV>!Am7u5`ONmRgx%k@`=uLYz>v?OGi%`ayXoJN-LOW=jb{F#!HyD z6)vV?EIvl~8rpHUeMQ-(?LimKop&%(1IW57H7w#Ws9e2Gq zLLwWGf&P!$&i|MUAY@3s-RAWWQ-D;|$n-(RL0>Gub&bqJk4*kAwsqg&LJHt6O*o(k zKm#=n!`r64&{c85eyGz)5~_A(T*YN?)xSVEy4!Lk?Cspd<{AFVA{W!&bxB7>*`sUB zgN$Y-31oWjPB{PSUFO@qrFE7!{bKK@8{uhbx_(*Qm}Tvbrn;gl)A%e$DVWFgrToaR zNZ~kiKH?E73wx!0WpTt2K7=G2K)4`zc6bT^p08>`|6kS$h&=1P9p_p>7=s6kjSND8 zp}L!1J3Y+_X%eUjh*+>C&#^b14q~l2SdoDDa;dzR-MiJ;*TdIpUOWgrIkWyS4V6n$ z;~zB4V%(RCW9eD^lg}4nn{Pe+a`$HpLWQARx>sW)qU8`MXEOQ5WK?Ci{-rPcfot@_o5$!)Y6pC5;|SsIt)YaIuCRgx=F zNlwI0IzU0d3k5>Xi}kC`d#f+7j)Ba}6aJks_!wA($wM{&DOIo#$2k;dPF^^7zR=Yr zF)?r=MpUt>An3h=Rg`_9J{+j9H1ZG;QyRZ-moH7vojrH{D*X4aNE);eK`wI~^DG7{>w*96b&mHBiR^xwM*M?M1j_(tYb~8 zmXN{~EzD;5iF!PK46WM6y62z;kVu4&p9d$^-%|S?^-(DLC2grW6lnm_z!wkl3V1Q! zRsW4-0+pio?u5@u)+0khFy>i-FKJ5d;DY#C=}Vbi{ju|lEZqxKYFfd9ch%HH7sd2< z+Z`ah+vu<7(iF}jS>;Gj!bZ>W=ZyP|jTa;%HC{Q6y6h&uQTN@D4&$7GPk%9FV!&s> z+XZ##&-O0zWZO~CL+HqnKu6hN{UE2L&`xIpEEs>>{8e=80p)xN6;l}nWDYoX#g=vQ;9 z)|KQGYTT1ec-udI>>$0U(?W_;&rqOk@G%OS+upc&hqmFVZXk=#Bws{#KX#o;OngzD z=d6>7$t(Sir(;1jmE^7p7xb-aH>XIi3FNAHv>4XsElO$ViAdL-JBtZs%bZs)u53 zaRYBn7)pmKGgC4KnBve@+_MB4QcwAH-hiGY#G@?)aNU?essYi1; zB=#tqaVHn$t*u-Bdg=AnlTYG~IZI%ZP;(A&k0_ku9Y@2*{HYxebcD>$d?#=Sbz0Is z2NqHCmu99|WDz#OZ4}4~sB`;R+y-29Ja0pJm>L@&KLOkr9wOM}inDy`X?T>%%F1%D zHlUsI`gDOe(&Sa=rsdf98@UX{k#Rl0{tQ?!_smi$hWpesnV31U^sQ`;%SXf)Q<0Ac z+|9fZm*%5*m_f%c#3Yv9uY-e3ah$eqWrj)t@l5MiuW%I7GiA)>$lXmzz`Rx#d^ER( z7AB-~?uBxP@X(#8SG-#qL(Irgbc`>mUcM^qHGzmCg4godkd7c~B$@v(;s+tt!2;e@MK zsp{YuAMoDY2-ucV16muft;@+kk-?#?(1ZimtC~0ABF)~HF+7U_w7S~Gny{CFN>%I&)tsdU*T;G?Z>+6u2i@p~@?NUip5g_*;2(b1BW*|oW#XY^x9Ig#qV}?{E_pAfX z@fi>({%b}58kz(?`5zRR@GJWks7iO1&UN%pG%g&GL>=b7t$sU4-re!ybx*EIi_`byn*c?U15rfS|Tk*Y%+hcvv`{eCL+jAsv0@dqX6wfHeitYt?0!fhh;x-VP)# zIsrqs?{$Cg;kX1;G5n|sIjgbHmF4~>u`fR5**+(b;RMYcwvHOz&e20lSbu!b`Y}t^ zQ81-<0i%}Jb6ynj>#S|mYZHc#Er>%Jyi>0yj+)JfhYK;4YThNC#y_L?yD7A<)%zxh zvXg4&4=*7pi&m_89O`2!V83x2<30AGKj_yF#i%ZV7-11TmwW;7`oMx_ZQ;9K^;G@ zgnO5rWN0R8J1{bwsuQy|1T}IkJi}~68qSajTgg_IoBz_|wdLr|KE#howw!xOdg+kk zXitc3)ty$SN#%yp8*Opg=k#t3*{wb}qTGR*0+ICP{Hgh&*U7CLnH9ssFnoq$#b3YL z@SI)Qh#&{>q7#P3%MOJe9M$0e8uuOZG{E2vk|}Urj*hTX2Sh-42uQ+o{Q6%JDvucj z!7u2PsE~n69(VyNUOhOHoTefl!0)26h~kIGD|gV7z8rY*5Xjfi3EE=zk3^u6jl-_G zLG1|u>dkX}muBRe4T}sJc`da{FIjDvXh>!sZ;ao)N_egG8kgxHJ3zUqJObL1H=^}7 z*BN`2I)+VpKlwOQh*0|JURk{LinV5g*U9Sw5bbxuX=y+6c_UOxZMMVYD{IxuvFGUo ztnG&;Qs9A01Y+4}WhJ$MRbC%)4Fy{SrnIyf)>)N!?21R3X!LjwBH^kUfhg75 zJ~%W<9ceuSUiKbf=r`e1q-@%N){FZ4g#& zNtaX%7qpd<9L07_=~REdxZW*0?2UukZ>46vF~M2%!5UpLsn5H8&#^|9H2R8Wtqn{5^2t>g1*$_40cTZuw8n*Y;nG9 zbZ&K#!jrfj0k#RiA3b9)4yD70`?|s1^d1rB%7gp6A$`7_87j+{8KEYz@7|Ce+UhvK z%gklTXO6LXP^^NgiUqjrKwN{%4ATY9fQwA5p zJMoZ!@pV)(lb`~?U$V%+;`{ges1g@ngetx=x$f6;?Tfc2ZZw~p3MdV}yZ`6dv^s`8_onPcjZf}YC zSR(b`)YAE^W*zKCAtArrlkD&vOR!4*s3#OiP&)j>K}7Slnr?%`2N)|*;fpK)NEPax z1o_KeJPo<^=@ifrReexTf!+c41{72nsp<;M7b-Zhz{Y6>-)8X;p7+V zFC6eUoPX2JQ!_JvC>KHaCQ?gH_zYAUk&OiYW#Q%d!6HT6y8|nN3a-oHf|eGnjQwlA zKo;u3ZOShyB9?AGPRIUJVK(b?QNb;4)61!U)Z_)o33b3<2|WUKfBptMbLWcj0W@1m zcr)?zhZ|GZm%K%Vt6FmRt0@#da&=Q!(S&i38>76?yqK}$g00L#l)>B~`SuCT92`RS zjk&5(H)*lAZGuw1cE$3aD^Nbux7ytE?!8I-VRqeX?M%&hTg?_ZgqDfua>;bw0dZUEVGl#&r=eT+tbn>UV z*9Mb-c_nCP_trWXfWzsvi7wSik0C`I0+M1A)C%A&gK3z!XNBO$@MuXr_m{4*EX!>_ z%#!hn`p|G!_tlef>H#?Wvfz}lAjm2p0pIoA;oBf-o904T{5Z~`c*dnpC<_>jqokZQ zUsMgL8^d@uA`bPfypHf;rR+u|*>-a(YV5E+7G3`MATUj_Q6p70&NNLImavTe9MbUC z&gfkBdiU<^;e*%Oc+Z>ht2{0NcsviDJ7)%C{8M&+4OuFY{BDoJZJwXU zx|B5&m#0_O$B*b1^RWn1^18QF17F;tY?t5LybtSqI1?vNEe9wi?p1C!)A}*m7biNY z?lk}AB5{^bfJDgPN;}Uq{Ho5zs>yOi4Jyy~VZ@sm+vBkNnv|dU+?~@<%KrhS2h1{X z5L*jC_Zc;pnX+YQEr3W4Wiiw+2i5#P!sGVCxI9du-5Zy5&4Nr^llMeRaen0;_&L%vK z0U3V!l90{2ur!{mtgZ#B?yJF1r2Qvc%;WA->xJDc@56pODLp!3Qe|i~??QW`=frI? zo?~1-PU!#ThO7$nmYjl8xG}qs|2Gyvtsn-!11`YI?Sl4!WeCu)Vz{-v{U0BNf3U3g z*%Qu;g%l@(8E;aL2UW-A0e&@l$QdPe#VnndA`2}{&ThXtG9SvJ0;oq(&>}0*gyCse z@f9^zGTCvCOJwX&k_H;Pp=!S}h>*)xH2dVwiO{QH;aB`B6vjtScOw#BiA;aSWjG9B z#gOt_r+!@6oArM%P*tiBho%yhWvgO&>ZeAwqzp3! zf$M>K7c77iqHt_NCa8~+z`ujeNhD_K9p}|u#HF$%l-T9f|Kwo*(GVx}UVP)8wD>OY ziTWs;MEN#OLo=|p@rUzrQA26Nu?DvgMfxZ7jOt7xOyx(_+nQE^LP<$r4?L41YBIkC z=e?sKAmyk^Z`akcYF!9YIiqu5?(`hh(t>~2y03NBp8#4VuALKH ztDt&8zderOBgCg|7d@#2%DRp3#((W&<2IRDEfQ9SDf(@g{FjOObNO&Fewqg*hzvM6 zL~00iUdBgdzN5eyUa$$otBSsGn5D`vDXUcUydK+iLA0K0z4QpS0pajsuwKxf!k6i# zyx5?Q(yB!JZziCg1n9u%V}QmNG7JhG-|VM!<+7#POa zT~30VlQgBoQ!jFfB+MVK?G9mod!M)p3FVK%k8U~w5yl$ z@%*~ARMLsdZ@y*AP0wjfpV#8Nd52!^!_$v}ULtGO^31@caS4gF0yj3DWdgCKLs&N^ z+bI4V+9-^J$1gWIn>XD{r9=4hl@ltxpW9|@KX8XY&_Sp)Pbu50TndRm9+K5H)AD1Y-K|%8DT6=J*?d4dM@l z{TY@e!mjH+GyIQTcH7b+M`3=psuNjR%V2u>{lDTn92n4YHTa`DU!=vGFoaBi)J*Q> z32qYbB@wE&a}hV_;F3Q+P}FmDRWq!9knPS%C2)Maa*zNL(@XVy*GJvoTu#zww|W?) zpY$@LbEI2HH!k_Scob6OvmKO}&mw7n|HP8_-aUroG3uIv+Vt3v4tUqd)WOY)NL)TJ^%fmD5r5_>TzA@k*R>b2s3atAI^&_MyVX(Q*5cHx)B={(thav1DK6<`&-pr zs~A-*VRwYE!~$O;TlIE%b*lhsQwgZ-J?zfBnao5^@rcX#1bnk`|0gLYRlpZ-0h}wi z27v~KVg#C+h)$=alj%sP7r?|!w1tFofPX)n!#oZoGq7THnUp!wE5|yY{`6YQJ7Tu z7J4Rb>nUZlcdXMQv@W#@hi|_7ceBI1XqY(f|n&`%J@NY1?eALSrGoIWOl-cv_@&^?5})@BRoYGBJ`A?Jb)<$_*DRo;19^x z;ZV7MXk4^$Me@a9)IVR&X!3i;``w&l%|ksAX@^TCs!2o*R#FpoTt7+>P#FIgc3Y!= zLPm#|3T+y1(R@X{vkAazb)yMamUiAAYC195QN;p=zAX`^*VLm4P#-qDdGzSP(vC}b zb|w%8NN_O%(E@e=qRYR4kKdr|cBy_9*9^=9)PaGeq&(n-AexP#a;(_j+x9VXQe{o= zHV4fg-I_NDR9vzlEz(K*i-5OdQ~G6$j^a+0ixpx zLhs(D%sw70QI7>nxWZt&Co#prc-D=o&c}j}!Q-;VAa@$1E{Mw`(3S%;>^NBYh>yK= zVI!kM{6U?=-rhdmN^&l_;+^JKWt?u^pL?h#s3jC0NE^+yKBQFO&oj`e>Cm0D6XTsa z4DTTG5QD9@dm&6KhVprgGsHE&%7F!4~SFflSfn(cqsHvQJoi z9FRLZY4PSsH)r6JtvVr@iZ2~=b95V*_X(pWx!TS}0^gLT!KT9^9CM@B<2(E5M_eRf z_%5J9i!F!6R~*3`xFfLNy1(3&$YutnLDw+?Sa!@F`4c;p%q%m&1Fx?dhsH#{UpJ1M zo}WX0ktih;1*SZve>64IU?X`s(&n6&7Qy983b(k3xX1T?@GHPaFC1vwKzT z&Ob&+lSui%E(>nY*j0k)h3$kqS0=1u@GkrxKYtWH2h+nzPmm;*mX`R!Y{i)k`oJ9i z6gtN&i-m|r!dJO-fX2~CAfN%XAsCm+A)SDSAQhSq@LSt1iIcm3&Wfq7bKz$Pf($xv zyUotx@$b3BR3EWyVzu7T5B%+Ke4f89Sm#t|_wIhV&WC!5*`|LI>9Gj|YuwjMAZ)9Gk= zTAuv;+=)p(yEXl?WaB|G##IUi2F3SX=R=zBsK>0)G=ozlGlGL5f|XTCBydU+AI%6_ zM%Gu3n5xj0sl&atZ|#&$x_F-kHM~ySKe9n=Zz{>Xqk3~OlskIaEM%8YV9wcP+*pRk z+hf!nrJCp38GiJJA$3{q%KF~O=!DEx=w7N-1+T5cYIpo^Xo{H-?TD=&?C<}e7K2vY zs_G;<+SXUs2CX`)7GIV#F)U3^ZAbyfyldQx!AFb-Ge3q<4fp8y$Zcr1 zQP0tSH5>m241uVz{!yoi-~nG~%Y)28D9C z+*dYC(DHEu;5E$g5B@_OcJ630)85%B^QX*A_Z;-nV9wrx`;^ME8vu6L=!4#&SNhw3 zfw$6gXOEDiozm;SIoT2kBIFk<6zOjD@zAa4M7_>c5s|XLl_5bd6niwr&ksqj8Axg? z=AAqNTmC3cnj+zY4?DR1GYJ>Ha-GJ-%g zMat7~#nAHZ+Gn>*Hqo%N*U)`c>(Jg9)t=|0opHL+=9RT=cgU6=p+pk&`$MbtI6vtS z1)f){kl{#vPenhn-P_p|DR$M>$m6)WVcEGX35znpdR}XeAo^Rt@cUxW6xt!(q+$06 zW`rT5-Cotz42Up~?P63sH0+;m1!ESmcL0o&;Ho}I)SwpM`}IUGN-nkgG4#A8OI>H4 zk|d5)e+tkW4Aq9HT?c6VG#Hc#KqDa^LstW6e!yP?v)f3_1|r4L>$nJp?baO+m#+RP z$>9Z)gMjd?u*6{wy6gPG-nrd_Aig@dtYV^~V=&X5*Z{>!22$W{b^9KAbtsjf{}9s7 z{lh2FmqUrowm=C(?Z49iWt`dNSIpPes`vW##ep4z4~|+N-F4jA>Z^wSHe&Mzj6=8X z+---`mDtcfwQG;EP3+*rD|X=eu#lWAZ4(pQh#zbeC$1{9JVD$uG>$!%%VKS9-v-{obND&FD{V^+!Gjex zOIqI_L~mT*+o770lzNrFzYxL9n%+o3TvI}*CJ=r)SiwKqv9JcCB^ zV~iRyc8@bYp7^W3x^-nz^c2w=4m*6m-*B|EivVBZ0|KQde3j7OYQtoveeD^%5aO}h z+a@-#{;e$rNTmZW!re37R-^TWUkm0{+^powy5YQ}j3uWwYf%{N4lat1!*4mAzpt&s zoz1t1hx?wR%}!b8e@u+{CPw?#adl13W!2F?CB;HS%8!M}vjbNMP2aiad+uexdK8fS zVftqSY<&UM6mmZk7V|j&pj=VskJi=Efj*8AtvJHQ2K``BtTHF~ZptmQSXOl+i2nK{ z(GY-)uyz z!J>+HdMH)2bR?3X3^&Qu8=ol&6?r)zAqhxuNAV87S;{P*#<7gLl*<};Mr9H;$#O2+;eD?E|HxrgX-W?cq>? z$T;A~A-f7aQ~^N?ygue}*IF-vGGkvptb4B6pT(oe6^uY#FTybY!#=~UI`vSM4k-K{w=zB-Hj$2)XeyPXFU#PJ;*pwB>kecGB|1=oZOfx$6h+cgtdYtsq$< zROI^XNA_~w42{T)Z$+#87?yrCGz7LvU|yqsg_#EFQw<99yi)>cjA%ead{ze8T=a$G z>;LsJCv$%md|*PDi79;gHg$rTjxbXV236><6NuT|bcV0C^MxR9{hR-Eif$j1`6~-y z#5VzA%`Ywz-MP?u2Npv(;3m45kA-NYqlqH~V&L!0bUA>311p*J=CTR&4(%#*9EI6u z2V&E}_1tt6EMx`Q$%tMWL8?KXC2N#4k8cq=RmIr zQ8uN3Uaj*cGyi&m|^&Tt(-SljrjRkz-Hu@uH55Y=nr98u{DXMXD-ea*z&-NHGja*hM5_S-4e9%e{^ zR)v zs%w`K`jFVdBR7r514{}Gk6hu&Tz{d%%ClVUpSzBu<1Ji$O@rtD^;9WGd1%#YtDiNL zs%`_qPJa*6iDYKRT@angx=VWrzN%lnG(Z!ph=Ab#v*}XcMLw7m;ryy1!FZx~rC;oM z(Iaq|yK?+>mxo6XnFO%1VcJ58Z6FMx@&Q(6lFYbSd*I7;qU1{T6L%LoB5R=qfS!^* z6zkZVFLR~S_Qy9zh>tL~Byt7cDPzkj`+qBvlM`JIySZN*ifznTr{pqIxxu~9d^Lh! zFRc z`c@A7(=`Ur-SFz%=z8;%EhsF+cmX2*%&CijX_{2wVyVeVa?6D7R5} z0GunwK|8<@_J6_3Z&i~|vThF+`y?jjF8g}3eiftyt*BK06ja;1owhI(!b#Fpl6k_J z8RkX6MV4F^MW}$uIucBjVD$hWp8Kam0VcXJ=+`OSjw(zZXC{`MzEcux;`GSbs;Zga zDLQ5x_?E#902mpVPvEKO{a}&(4B4FP!ugbg4#fKLX+(7^!O$pG4M2R2RF zu1n&PT@C*+f1td@)`Zw^nx?}CmN+Qc2aA&K_$3~gDyTan5GqKAt@&$Ivw!@7_Mva! zPz*GhdH2SdsV`Nt2?OyCS#=Mj3P?zNlOW3&)A*I_9mNTLe1PaF{bkUOb5MZ>zm|r> zCswXzO^tss+U)yJ^ZX^QeSevHVk+tA=$PMz4!La?a10P3t)s<04#rF5CruFB&hmB( zs~fHM*Q{0ud*%E5R@J-L0GWS9{9eMMcCb6^`@5)4Ytf@)0{c_dJHd$xZmvXZWQM;f zsSgG@#R7ziy4G1092`5a4rbtf0{;c=m&!Pfz?1=>A+Xou5HAMh`&LEb-(YQ&t4Fa! z4>)*BAqTa?#Fa!m39c9W2$kev5M{!|!mA#Z=&5yXM}fAuX$!q5F$jhCKIqCzrTL78X6h+MF=1=)Ii2DgIERxa4y| zQ~%0lDRtXqkF{0ku84 zOtt@0MsmfGSk=LgZUdR^Yp-6*?BZmmRQLa=vXr!|qPFhuW$*v04nG^#*#!8%>)9*B z$ErL&qUB6Jw{%KFAw^Xr9E-I$;{4mK$suE=zr#S5=mx7EEojjBVL<(T}~BC$=AcjVb)l&vou zXAh}XAA@$yq3(cZrOLvLKMVDoLMx-`hSmkg*z1dJs+G&~R*0@is3$N%;t;gk8@G3* zK>`KMrBKgAlKFn#=r$WSFaUGnQ1nCG+N*uEaRRWBrdB%aJZhmyEEAcrg<+7civ}

Nm^I@ru>&4?A5-E>f!N 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 z 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≷rh$B6qr@rG*oX?l_uN_VKj=aWB>- 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 KQ^RMk`@aBoEqogQ literal 0 HcmV?d00001 diff --git a/benchmark_res/result_small_parallel.png b/benchmark_res/result_small_parallel.png new file mode 100644 index 0000000000000000000000000000000000000000..51b9edf150483dedda25966dcde26a536a0e2967 GIT binary patch literal 118617 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 z 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 a5A9X4^1#ev?E@A3XE)8s=7hE9`u_m{3bwca literal 0 HcmV?d00001