From 406fd40a7e6a9fb45ae4dfe868affdadb6d01911 Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Thu, 30 Jan 2020 16:44:45 -0500
Subject: [PATCH] Add USE_STBIMAGE for LoadPNG/LoadJPG, USE_TINYJPEG for
SaveJPG
---
IMG_jpg.c | 168 +-
IMG_png.c | 47 +
IMG_stb.c | 150 ++
stb_image.h | 7471 +++++++++++++++++++++++++++++++++++++++++++++++++++
tiny_jpeg.h | 1285 +++++++++
5 files changed, 9120 insertions(+), 1 deletion(-)
create mode 100644 IMG_stb.c
create mode 100644 stb_image.h
create mode 100644 tiny_jpeg.h
diff --git a/IMG_jpg.c b/IMG_jpg.c
index 0be00039..c71c3581 100644
--- a/IMG_jpg.c
+++ b/IMG_jpg.c
@@ -551,6 +551,95 @@ static int IMG_SaveJPG_RW_jpeglib(SDL_Surface *surface, SDL_RWops *dst, int free
return result;
}
+#elif defined(USE_STBIMAGE)
+
+extern SDL_Surface *IMG_LoadSTB_RW(SDL_RWops *src);
+
+int IMG_InitJPG()
+{
+ /* Nothing to load */
+ return 0;
+}
+
+void IMG_QuitJPG()
+{
+ /* Nothing to unload */
+}
+
+/* FIXME: This is a copypaste from JPEGLIB! Pull that out of the ifdefs */
+/* Define this for quicker (but less perfect) JPEG identification */
+#define FAST_IS_JPEG
+/* See if an image is contained in a data source */
+int IMG_isJPG(SDL_RWops *src)
+{
+ Sint64 start;
+ int is_JPG;
+ int in_scan;
+ Uint8 magic[4];
+
+ /* This detection code is by Steaphan Greene <stea@cs.binghamton.edu> */
+ /* Blame me, not Sam, if this doesn't work right. */
+ /* And don't forget to report the problem to the the sdl list too! */
+
+ if ( !src )
+ return 0;
+ start = SDL_RWtell(src);
+ is_JPG = 0;
+ in_scan = 0;
+ if ( SDL_RWread(src, magic, 2, 1) ) {
+ if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) {
+ is_JPG = 1;
+ while (is_JPG == 1) {
+ if(SDL_RWread(src, magic, 1, 2) != 2) {
+ is_JPG = 0;
+ } else if( (magic[0] != 0xFF) && (in_scan == 0) ) {
+ is_JPG = 0;
+ } else if( (magic[0] != 0xFF) || (magic[1] == 0xFF) ) {
+ /* Extra padding in JPEG (legal) */
+ /* or this is data and we are scanning */
+ SDL_RWseek(src, -1, RW_SEEK_CUR);
+ } else if(magic[1] == 0xD9) {
+ /* Got to end of good JPEG */
+ break;
+ } else if( (in_scan == 1) && (magic[1] == 0x00) ) {
+ /* This is an encoded 0xFF within the data */
+ } else if( (magic[1] >= 0xD0) && (magic[1] < 0xD9) ) {
+ /* These have nothing else */
+ } else if(SDL_RWread(src, magic+2, 1, 2) != 2) {
+ is_JPG = 0;
+ } else {
+ /* Yes, it's big-endian */
+ Sint64 innerStart;
+ Uint32 size;
+ Sint64 end;
+ innerStart = SDL_RWtell(src);
+ size = (magic[2] << 8) + magic[3];
+ end = SDL_RWseek(src, size-2, RW_SEEK_CUR);
+ if ( end != innerStart + size - 2 ) is_JPG = 0;
+ if ( magic[1] == 0xDA ) {
+ /* Now comes the actual JPEG meat */
+#ifdef FAST_IS_JPEG
+ /* Ok, I'm convinced. It is a JPEG. */
+ break;
+#else
+ /* I'm not convinced. Prove it! */
+ in_scan = 1;
+#endif
+ }
+ }
+ }
+ }
+ }
+ SDL_RWseek(src, start, RW_SEEK_SET);
+ return(is_JPG);
+}
+
+/* Load a JPEG type image from an SDL datasource */
+SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
+{
+ return IMG_LoadSTB_RW(src);
+}
+
#else
#if _MSC_VER >= 1300
#pragma warning(disable : 4100) /* warning C4100: 'op' : unreferenced formal parameter */
@@ -587,6 +676,81 @@ SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
#ifdef SAVE_JPG
+#if !defined(USE_JPEGLIB) && defined(USE_TINYJPEG)
+
+#define assert SDL_assert
+#define ceilf SDL_ceilf
+#define floorf SDL_floorf
+#define memcpy SDL_memcpy
+
+#define tje_log SDL_Log
+#define TJE_IMPLEMENTATION
+#include "tiny_jpeg.h"
+
+static void IMG_SaveJPG_RW_tinyjpeg_callback(void* context, void* data, int size)
+{
+ SDL_RWwrite((SDL_RWops*) context, data, 1, size);
+}
+
+static int IMG_SaveJPG_RW_tinyjpeg(SDL_Surface *surface, SDL_RWops *dst, int freedst, int quality)
+{
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ static const Uint32 jpg_format = SDL_PIXELFORMAT_RGB24;
+#else
+ static const Uint32 jpg_format = SDL_PIXELFORMAT_BGR24;
+#endif
+ SDL_Surface* jpeg_surface = surface;
+ int result = -1;
+
+ if (!dst) {
+ SDL_SetError("Passed NULL dst");
+ goto done;
+ }
+
+ /* Convert surface to format we can save */
+ if (surface->format->format != jpg_format) {
+ jpeg_surface = SDL_ConvertSurfaceFormat(surface, jpg_format, 0);
+ if (!jpeg_surface) {
+ goto done;
+ }
+ }
+
+ /* Quality for tinyjpeg is from 1-3:
+ * 0 - 33 - Lowest quality
+ * 34 - 66 - Middle quality
+ * 67 - 100 - Highest quality
+ */
+ if (quality < 34) quality = 1;
+ else if (quality < 67) quality = 2;
+ else quality = 3;
+
+ result = tje_encode_with_func(
+ IMG_SaveJPG_RW_tinyjpeg_callback,
+ dst,
+ quality,
+ jpeg_surface->w,
+ jpeg_surface->h,
+ 3,
+ jpeg_surface->pixels
+ ) - 1; /* tinyjpeg returns 0 on error, 1 on success */
+
+ if (jpeg_surface != surface) {
+ SDL_FreeSurface(jpeg_surface);
+ }
+
+ if (result < 0) {
+ SDL_SetError("tinyjpeg error");
+ }
+
+done:
+ if (freedst) {
+ SDL_RWclose(dst);
+ }
+ return result;
+}
+
+#endif /* !defined(USE_JPEGLIB) && defined(USE_TINYJPEG) */
+
int IMG_SaveJPG(SDL_Surface *surface, const char *file, int quality)
{
SDL_RWops *dst = SDL_RWFromFile(file, "wb");
@@ -601,8 +765,10 @@ int IMG_SaveJPG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst, int qualit
{
#ifdef USE_JPEGLIB
return IMG_SaveJPG_RW_jpeglib(surface, dst, freedst, quality);
+#elif USE_TINYJPEG
+ return IMG_SaveJPG_RW_tinyjpeg(surface, dst, freedst, quality);
#else
- return IMG_SetError("SDL_image not built with jpeglib, saving not supported");
+ return IMG_SetError("SDL_image not built with jpeglib/tinyjpeg, saving not supported");
#endif
}
diff --git a/IMG_png.c b/IMG_png.c
index 418bf972..d4a45c4b 100644
--- a/IMG_png.c
+++ b/IMG_png.c
@@ -449,6 +449,53 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
return(surface);
}
+#elif defined(USE_STBIMAGE)
+
+extern SDL_Surface *IMG_LoadSTB_RW(SDL_RWops *src);
+
+int IMG_InitPNG()
+{
+ /* Nothing to load */
+ return 0;
+}
+
+void IMG_QuitPNG()
+{
+ /* Nothing to unload */
+}
+
+/* FIXME: This is a copypaste from LIBPNG! Pull that out of the ifdefs */
+/* See if an image is contained in a data source */
+int IMG_isPNG(SDL_RWops *src)
+{
+ Sint64 start;
+ int is_PNG;
+ Uint8 magic[4];
+
+ if ( !src ) {
+ return 0;
+ }
+
+ start = SDL_RWtell(src);
+ is_PNG = 0;
+ if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
+ if ( magic[0] == 0x89 &&
+ magic[1] == 'P' &&
+ magic[2] == 'N' &&
+ magic[3] == 'G' ) {
+ is_PNG = 1;
+ }
+ }
+ SDL_RWseek(src, start, RW_SEEK_SET);
+ return(is_PNG);
+}
+
+/* Load a PNG type image from an SDL datasource */
+SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
+{
+ return IMG_LoadSTB_RW(src);
+}
+
#else
#if _MSC_VER >= 1300
#pragma warning(disable : 4100) /* warning C4100: 'op' : unreferenced formal parameter */
diff --git a/IMG_stb.c b/IMG_stb.c
new file mode 100644
index 00000000..f8ba197e
--- /dev/null
+++ b/IMG_stb.c
@@ -0,0 +1,150 @@
+/*
+ SDL_image: An example image loading library for use with SDL
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_image.h"
+
+#ifdef USE_STBIMAGE
+
+#ifndef INT_MAX
+#define INT_MAX 0x7FFFFFFF
+#endif
+
+#define malloc SDL_malloc
+#define realloc SDL_realloc
+#define free SDL_free
+#define memcpy SDL_memcpy
+#define memset SDL_memset
+#define strcmp SDL_strcmp
+#define strncmp SDL_strncmp
+#define strtol SDL_strtol
+#define pow SDL_pow
+#define ldexp SDL_scalbn
+
+#define STBI_NO_STDIO
+#define STBI_ONLY_PNG
+#define STBI_ONLY_JPEG
+#define STBI_ASSERT SDL_assert
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+static int IMG_LoadSTB_RW_read(void *user, char *data, int size)
+{
+ return (int) SDL_RWread((SDL_RWops*) user, data, 1, size);
+}
+
+static void IMG_LoadSTB_RW_skip(void *user, int n)
+{
+ SDL_RWseek((SDL_RWops*) user, n, RW_SEEK_CUR);
+}
+
+static int IMG_LoadSTB_RW_eof(void *user)
+{
+ /* FIXME: Do we not have a way to detect EOF? -flibit */
+ size_t bytes, filler;
+ SDL_RWops *src = (SDL_RWops*) user;
+ bytes = SDL_RWread(src, &filler, 1, 1);
+ if (bytes != 1) /* FIXME: Could also be an error... */
+ {
+ return 1;
+ }
+ SDL_RWseek(src, -1, RW_SEEK_CUR);
+ return 0;
+}
+
+SDL_Surface *IMG_LoadSTB_RW(SDL_RWops *src)
+{
+ Sint64 start;
+ int w, h, format;
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ int shift;
+#endif
+ Uint32 rmask, gmask, bmask, amask;
+ stbi_uc *pixels;
+ stbi_io_callbacks rw_callbacks;
+ SDL_Surface *surface = NULL;
+
+ if ( !src ) {
+ /* The error message has been set in SDL_RWFromFile */
+ return NULL;
+ }
+ start = SDL_RWtell(src);
+
+ /* Load the image data */
+ rw_callbacks.read = IMG_LoadSTB_RW_read;
+ rw_callbacks.skip = IMG_LoadSTB_RW_skip;
+ rw_callbacks.eof = IMG_LoadSTB_RW_eof;
+ pixels = stbi_load_from_callbacks(
+ &rw_callbacks,
+ src,
+ &w,
+ &h,
+ &format,
+ STBI_default
+ );
+ if ( !pixels ) {
+ SDL_RWseek(src, start, RW_SEEK_SET);
+ IMG_SetError("%s", stbi_failure_reason());
+ return NULL;
+ }
+
+ /* Determine the surface format */
+ SDL_assert(format == STBI_rgb || format == STBI_rgb_alpha);
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ shift = (format == STBI_rgb) ? 8 : 0;
+ rmask = 0xFF000000 >> shift;
+ gmask = 0x00FF0000 >> shift;
+ bmask = 0x0000FF00 >> shift;
+ amask = 0x000000FF >> shift;
+#else // little endian, like x86
+ rmask = 0x000000FF;
+ gmask = 0x0000FF00;
+ bmask = 0x00FF0000;
+ amask = (format == STBI_rgb) ? 0 : 0xFF000000;
+#endif
+
+ /* Allocate the surface */
+ surface = SDL_CreateRGBSurfaceFrom(
+ pixels,
+ w,
+ h,
+ 8 * format,
+ w * format,
+ rmask,
+ gmask,
+ bmask,
+ amask
+ );
+ if ( !surface ) {
+ /* The error message should already be set */
+ SDL_free(pixels);
+ SDL_RWseek(src, start, RW_SEEK_SET);
+ } else {
+ /* FIXME: This sucks. It'd be better to allocate the surface first, then
+ * write directly to the pixel buffer:
+ * https://github.com/nothings/stb/issues/58
+ * -flibit
+ */
+ surface->flags &= ~SDL_PREALLOC;
+ }
+ return surface;
+}
+
+#endif /* USE_STBIMAGE */
diff --git a/stb_image.h b/stb_image.h
new file mode 100644
index 00000000..062b6780
--- /dev/null
+++ b/stb_image.h
@@ -0,0 +1,7471 @@
+/* stb_image - v2.19 - 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.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
+ John-Mark Allen
+
+ Bug & warning fixes
+ Marc LeBlanc David Woo Guillaume George Martins Mozeiko
+ Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan
+ Dave Moore Roy Eltham Hayaki Saito Nathan Reed
+ Won Chun Luke Graham Johan Duparc Nick Verigakis
+ the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh
+ Janez Zemva John Bartholomew Michal Cichon github:romigrou
+ Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
+ Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar
+ Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex
+ Ryamond Barbiero Paul Du Bois Engin Manap github:grim210
+ Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw
+ Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
+ Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
+ Christian Floisand Kevin Schmidt github:darealshinji
+ Blazej Dariusz Roszkowski github:Michaelangel007
+*/
+
+#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.
+//
+// ===========================================================================
+//
+// 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
+// make 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 now supports loading HDR images in general, and currently
+// the Radiance .HDR file format, although the support is provided
+// generically. You can still load any file through the existing interface;
+// if you attempt to load an HDR file, it will be automatically remapped to
+// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
+// 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:
+//
+// By default we convert iphone-formatted PNGs back to RGB, even though
+// they are internally encoded differently. You can disable this conversion
+// by by calling stbi_convert_iphone_png_to_rgb(0), in which case
+// you will always just get the native iphone "format" through (which
+// is BGR stored in RGB).
+//
+// 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
+//
+
+
+#ifndef STBI_NO_STDIO
+#include <stdio.h>
+#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
+};
+
+typedef unsigned char stbi_uc;
+typedef unsigned short stbi_us;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef STB_IMAGE_STATIC
+#define STBIDEF static
+#else
+#define STBIDEF extern
+#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_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+#endif
+
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+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
+
+////////////////////////////////////
+//
+// 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
+// NOT 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);
+
+// ZLIB client - used by PNG, available for other purposes
+
+ST
(Patch may be truncated, please check the link at the top of this post.)