From 52f4573762c90c36d81b3ab00fed4ecd0bf1d4d5 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Fri, 9 Sep 2016 09:51:28 +0100 Subject: [PATCH] Updated stb_image to latest version Notes: commented out requirement for memory.h (as original version did) Also should move to using stb_image.h --- stb_image.c | 2400 +++++++++++++++++++++++---------------------------- 1 file changed, 1069 insertions(+), 1331 deletions(-) diff --git a/stb_image.c b/stb_image.c index 918dd80..1737876 100644 --- a/stb_image.c +++ b/stb_image.c @@ -1,4 +1,4 @@ -/* stbi-1.28 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c +/* stb_image - v1.35 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c when you control the images you're loading no warranty implied; use at your own risk @@ -7,7 +7,7 @@ avoid problematic images and only need the trivial interface JPEG baseline (no JPEG progressive) - PNG 8-bit only + PNG 8-bit-per-channel only TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE @@ -17,53 +17,50 @@ HDR (radiance rgbE format) PIC (Softimage PIC) - - decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code) - - supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) Latest revisions: + 1.35 (2014-05-27) warnings, bugfixes, TGA optimization, etc + 1.34 (unknown ) warning fix + 1.33 (2011-07-14) minor fixes suggested by Dave Moore + 1.32 (2011-07-13) info support for all filetypes (SpartanJ) + 1.31 (2011-06-19) a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) added ability to load files via io callbacks (Ben Wenger) + 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-uint8 to fix warnings (Laurent Gomila) - allow trailing 0s at end of image data (Laurent Gomila) - 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 - minor perf improvements for jpeg - deprecated type-specific functions in hope of feedback - attempt to fix trans_data warning (Won Chun) - 1.23 fixed bug in iPhone support - 1.22 (2010-07-10) removed image *writing* support to stb_image_write.h - 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 - 1.21 fix use of 'uint8' in header (reported by jon blow) - 1.20 added support for Softimage PIC, by Tom Seddon See end of file for full revision history. TODO: stbi_info support for BMP,PSD,HDR,PIC - rewrite stbi_info and load_file variations to share file handling code - (current system allows individual functions to be called directly, - since each does all the work, but I doubt anyone uses this in practice) ============================ Contributors ========================= - - Image formats Optimizations & bugfixes - Sean Barrett (jpeg, png, bmp) Fabian "ryg" Giesen - Nicolas Schulz (hdr, psd) - Jonathan Dummer (tga) Bug fixes & warning fixes - Jean-Marc Lienher (gif) Marc LeBlanc - Tom Seddon (pic) Christpher Lloyd - Thatcher Ulrich (psd) Dave Moore - Won Chun - the Horde3D community - Extensions, features Janez Zemva - Jetro Lauha (stbi_info) Jonathan Blow - James "moose2000" Brown (iPhone PNG) Laurent Gomila - - If your name should be here but isn't, let Sean know. + + Image formats Bug fixes & warning fixes + Sean Barrett (jpeg, png, bmp) Marc LeBlanc + Nicolas Schulz (hdr, psd) Christpher Lloyd + Jonathan Dummer (tga) Dave Moore + Jean-Marc Lienher (gif) Won Chun + Tom Seddon (pic) the Horde3D community + Thatcher Ulrich (psd) Janez Zemva + Jonathan Blow + Laurent Gomila + Extensions, features Aruelien Pocheville + Jetro Lauha (stbi_info) Ryamond Barbiero + James "moose2000" Brown (iPhone PNG) David Woo + Ben "Disch" Wenger (io callbacks) Roy Eltham + Martin "SpartanJ" Golini Luke Graham + Thomas Ruf + John Bartholomew + Optimizations & bugfixes Ken Hamada + Fabian "ryg" Giesen Cort Stratton + Arseny Kapoulkine Blazej Dariusz Roszkowski + Thibault Reuille + If your name should be here but Paul Du Bois + isn't let Sean know. Guillaume George */ @@ -86,9 +83,10 @@ // Basic usage (see HDR discussion below): // int x,y,n; // unsigned char *data = stbi_load(filename, &x, &y, &n, 0); -// // ... process data if not NULL ... +// // ... 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: @@ -161,7 +159,7 @@ // (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: @@ -175,10 +173,29 @@ // not), using: // // stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// 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). + #ifndef STBI_NO_STDIO -#include + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#define _CRT_SECURE_NO_WARNINGS // suppress warnings about fopen() +#pragma warning(push) +#pragma warning(disable:4996) // suppress even more warnings about fopen() #endif +#include +#endif // STBI_NO_STDIO #define STBI_VERSION 1 @@ -189,7 +206,7 @@ enum STBI_grey = 1, STBI_grey_alpha = 2, STBI_rgb = 3, - STBI_rgb_alpha = 4, + STBI_rgb_alpha = 4 }; typedef unsigned char stbi_uc; @@ -198,9 +215,15 @@ typedef unsigned char stbi_uc; extern "C" { #endif +////////////////////////////////////////////////////////////////////////////// +// // PRIMARY API - works on images of any type +// +// // load image by filename, open file, or memory buffer +// + extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); #ifndef STBI_NO_STDIO @@ -209,6 +232,15 @@ extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, // for stbi_load_from_file, file pointer is left pointing immediately after image #endif +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; + +extern stbi_uc *stbi_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + #ifndef STBI_NO_HDR extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); @@ -216,6 +248,8 @@ extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); #endif + + extern float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); extern void stbi_hdr_to_ldr_gamma(float gamma); extern void stbi_hdr_to_ldr_scale(float scale); @@ -224,25 +258,34 @@ extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, extern void stbi_ldr_to_hdr_scale(float scale); #endif // STBI_NO_HDR +// stbi_is_hdr is always defined +extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +extern int stbi_is_hdr (char const *filename); +extern int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + // get a VERY brief reason for failure // NOT THREADSAFE -extern const char *stbi_failure_reason (void); +extern const char *stbi_failure_reason (void); // free the loaded image -- this is just free() extern void stbi_image_free (void *retval_from_stbi_load); // get image dimensions & components without fully decoding extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); -extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +extern int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); #ifndef STBI_NO_STDIO extern int stbi_info (char const *filename, int *x, int *y, int *comp); extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); -extern int stbi_is_hdr (char const *filename); -extern int stbi_is_hdr_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. @@ -256,30 +299,16 @@ extern void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); // ZLIB client - used by PNG, available for other purposes extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +extern char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); -// define new loaders -typedef struct -{ - int (*test_memory)(stbi_uc const *buffer, int len); - stbi_uc * (*load_from_memory)(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); - #ifndef STBI_NO_STDIO - int (*test_file)(FILE *f); - stbi_uc * (*load_from_file)(FILE *f, int *x, int *y, int *comp, int req_comp); - #endif -} stbi_loader; - -// register a loader by filling out the above structure (you must define ALL functions) -// returns 1 if added or already added, 0 if not added (too many loaders) -// NOT THREADSAFE -extern int stbi_register_loader(stbi_loader *loader); // define faster low-level operations (typically SIMD support) -#if STBI_SIMD +#ifdef STBI_SIMD typedef void (*stbi_idct_8x8)(stbi_uc *out, int out_stride, short data[64], unsigned short *dequantize); // compute an integer IDCT on "input" // input[x] = data[x] * dequantize[x] @@ -298,108 +327,6 @@ extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); #endif // STBI_SIMD - - -// TYPE-SPECIFIC ACCESS - -#ifdef STBI_TYPE_SPECIFIC_FUNCTIONS - -// is it a jpeg? -extern int stbi_jpeg_test_memory (stbi_uc const *buffer, int len); -extern stbi_uc *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -#ifndef STBI_NO_STDIO -extern stbi_uc *stbi_jpeg_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern int stbi_jpeg_test_file (FILE *f); -extern stbi_uc *stbi_jpeg_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); - -extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif - -// is it a png? -extern int stbi_png_test_memory (stbi_uc const *buffer, int len); -extern stbi_uc *stbi_png_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -#ifndef STBI_NO_STDIO -extern stbi_uc *stbi_png_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern int stbi_png_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_png_test_file (FILE *f); -extern stbi_uc *stbi_png_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif - -// is it a bmp? -extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_bmp_test_file (FILE *f); -extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a tga? -extern int stbi_tga_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_tga_test_file (FILE *f); -extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a psd? -extern int stbi_psd_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_psd_test_file (FILE *f); -extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it an hdr? -extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len); - -extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_hdr_test_file (FILE *f); -extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a pic? -extern int stbi_pic_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_pic_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_pic_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_pic_test_file (FILE *f); -extern stbi_uc *stbi_pic_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a gif? -extern int stbi_gif_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_gif_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_gif_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -extern int stbi_gif_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -#ifndef STBI_NO_STDIO -extern int stbi_gif_test_file (FILE *f); -extern stbi_uc *stbi_gif_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -extern int stbi_gif_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_gif_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif - -#endif//STBI_TYPE_SPECIFIC_FUNCTIONS - - - - #ifdef __cplusplus } #endif @@ -413,152 +340,171 @@ extern int stbi_gif_info_from_file (FILE *f, int *x, int #ifndef STBI_NO_HDR #include // ldexp -#include // strcmp +#include // strcmp, strtok #endif #ifndef STBI_NO_STDIO #include #endif #include -#include -#include -//#include +// #include #include #include +#include // ptrdiff_t on osx #ifndef _MSC_VER - #ifdef __cplusplus - #define __forceinline inline - #else - #define __forceinline - #endif + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline #endif -// implementation: -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned int uint32; -typedef signed int int32; -typedef unsigned int uint; - -// should produce compiler error if size is wrong -typedef unsigned char validate_uint32[sizeof(uint32)==4 ? 1 : -1]; - -#if defined(STBI_NO_STDIO) && !defined(STBI_NO_WRITE) -#define STBI_NO_WRITE -#endif - -#define STBI_NOTUSED(v) v=v - #ifdef _MSC_VER -#define STBI_HAS_LRTOL +typedef unsigned char stbi__uint8; +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint8_t stbi__uint8; +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; #endif -#ifdef STBI_HAS_LRTOL +// 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) >> (32 - (y)))) #endif -////////////////////////////////////////////////////////////////////////////// -// -// Generic API that works on all image types +/////////////////////////////////////////////// // +// stbi struct and start_xxx functions -// deprecated functions +// stbi 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; -// is it a jpeg? -extern int stbi_jpeg_test_memory (stbi_uc const *buffer, int len); -extern stbi_uc *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); + int read_from_callbacks; + int buflen; + stbi__uint8 buffer_start[128]; + + stbi__uint8 *img_buffer, *img_buffer_end; + stbi__uint8 *img_buffer_original; +} stbi; + + +static void refill_buffer(stbi *s); + +// initialize a memory-decode context +static void start_mem(stbi *s, stbi__uint8 const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi__uint8 *) buffer; + s->img_buffer_end = (stbi__uint8 *) buffer+len; +} + +// initialize a callback-based context +static void start_callbacks(stbi *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->img_buffer_original = s->buffer_start; + refill_buffer(s); +} #ifndef STBI_NO_STDIO -extern stbi_uc *stbi_jpeg_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern int stbi_jpeg_test_file (FILE *f); -extern stbi_uc *stbi_jpeg_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif - -// is it a png? -extern int stbi_png_test_memory (stbi_uc const *buffer, int len); -extern stbi_uc *stbi_png_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -#ifndef STBI_NO_STDIO -extern stbi_uc *stbi_png_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern int stbi_png_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_png_test_file (FILE *f); -extern stbi_uc *stbi_png_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif - -// is it a bmp? -extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_bmp_test_file (FILE *f); -extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a tga? -extern int stbi_tga_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_tga_test_file (FILE *f); -extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a psd? -extern int stbi_psd_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_psd_test_file (FILE *f); -extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it an hdr? -extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len); - -extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_hdr_test_file (FILE *f); -extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a pic? -extern int stbi_pic_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_pic_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_pic_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -#ifndef STBI_NO_STDIO -extern int stbi_pic_test_file (FILE *f); -extern stbi_uc *stbi_pic_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -#endif - -// is it a gif? -extern int stbi_gif_test_memory (stbi_uc const *buffer, int len); - -extern stbi_uc *stbi_gif_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_gif_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); -extern int stbi_gif_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -#ifndef STBI_NO_STDIO -extern int stbi_gif_test_file (FILE *f); -extern stbi_uc *stbi_gif_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -extern int stbi_gif_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_gif_info_from_file (FILE *f, int *x, int *y, int *comp); +static int stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi_stdio_callbacks = +{ + stdio_read, + stdio_skip, + stdio_eof, +}; + +static void start_file(stbi *s, FILE *f) +{ + start_callbacks(s, &stbi_stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi_rewind(stbi *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; +} + +static int stbi_jpeg_test(stbi *s); +static stbi_uc *stbi_jpeg_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_jpeg_info(stbi *s, int *x, int *y, int *comp); +static int stbi_png_test(stbi *s); +static stbi_uc *stbi_png_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_png_info(stbi *s, int *x, int *y, int *comp); +static int stbi_bmp_test(stbi *s); +static stbi_uc *stbi_bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_tga_test(stbi *s); +static stbi_uc *stbi_tga_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_tga_info(stbi *s, int *x, int *y, int *comp); +static int stbi_psd_test(stbi *s); +static stbi_uc *stbi_psd_load(stbi *s, int *x, int *y, int *comp, int req_comp); +#ifndef STBI_NO_HDR +static int stbi_hdr_test(stbi *s); +static float *stbi_hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp); #endif +static int stbi_pic_test(stbi *s); +static stbi_uc *stbi_pic_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_gif_test(stbi *s); +static stbi_uc *stbi_gif_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_gif_info(stbi *s, int *x, int *y, int *comp); // this is not threadsafe @@ -575,6 +521,10 @@ static int e(const char *str) return 0; } +// e - error +// epf - error returning pointer to float +// epuc - error returning pointer to unsigned char + #ifdef STBI_NO_FAILURE_STRINGS #define e(x,y) 0 #elif defined(STBI_FAILURE_USERMSG) @@ -591,33 +541,33 @@ void stbi_image_free(void *retval_from_stbi_load) free(retval_from_stbi_load); } -#define MAX_LOADERS 32 -stbi_loader *loaders[MAX_LOADERS]; -static int max_loaders = 0; - -int stbi_register_loader(stbi_loader *loader) -{ - int i; - for (i=0; i < MAX_LOADERS; ++i) { - // already present? - if (loaders[i] == loader) - return 1; - // end of the list? - if (loaders[i] == NULL) { - loaders[i] = loader; - max_loaders = i+1; - return 1; - } - } - // no room for it - return 0; -} - #ifndef STBI_NO_HDR static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp); static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp); #endif +static unsigned char *stbi_load_main(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + if (stbi_jpeg_test(s)) return stbi_jpeg_load(s,x,y,comp,req_comp); + if (stbi_png_test(s)) return stbi_png_load(s,x,y,comp,req_comp); + if (stbi_bmp_test(s)) return stbi_bmp_load(s,x,y,comp,req_comp); + if (stbi_gif_test(s)) return stbi_gif_load(s,x,y,comp,req_comp); + if (stbi_psd_test(s)) return stbi_psd_load(s,x,y,comp,req_comp); + if (stbi_pic_test(s)) return stbi_pic_load(s,x,y,comp,req_comp); + + #ifndef STBI_NO_HDR + if (stbi_hdr_test(s)) { + float *hdr = stbi_hdr_load(s, x,y,comp,req_comp); + return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + // test tga last because it's a crappy test! + if (stbi_tga_test(s)) + return stbi_tga_load(s,x,y,comp,req_comp); + return epuc("unknown image type", "Image not of any known type, or corrupt"); +} + #ifndef STBI_NO_STDIO unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) { @@ -631,59 +581,61 @@ unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int re unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { - int i; - if (stbi_jpeg_test_file(f)) return stbi_jpeg_load_from_file(f,x,y,comp,req_comp); - if (stbi_png_test_file(f)) return stbi_png_load_from_file(f,x,y,comp,req_comp); - if (stbi_bmp_test_file(f)) return stbi_bmp_load_from_file(f,x,y,comp,req_comp); - if (stbi_gif_test_file(f)) return stbi_gif_load_from_file(f,x,y,comp,req_comp); - if (stbi_psd_test_file(f)) return stbi_psd_load_from_file(f,x,y,comp,req_comp); - if (stbi_pic_test_file(f)) return stbi_pic_load_from_file(f,x,y,comp,req_comp); - - #ifndef STBI_NO_HDR - if (stbi_hdr_test_file(f)) { - float *hdr = stbi_hdr_load_from_file(f, x,y,comp,req_comp); - return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + unsigned char *result; + stbi s; + start_file(&s,f); + result = stbi_load_main(&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); } - #endif - - for (i=0; i < max_loaders; ++i) - if (loaders[i]->test_file(f)) - return loaders[i]->load_from_file(f,x,y,comp,req_comp); - // test tga last because it's a crappy test! - if (stbi_tga_test_file(f)) - return stbi_tga_load_from_file(f,x,y,comp,req_comp); - return epuc("unknown image type", "Image not of any known type, or corrupt"); + return result; } -#endif +#endif //!STBI_NO_STDIO unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { - int i; - if (stbi_jpeg_test_memory(buffer,len)) return stbi_jpeg_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_png_test_memory(buffer,len)) return stbi_png_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_bmp_test_memory(buffer,len)) return stbi_bmp_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_gif_test_memory(buffer,len)) return stbi_gif_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_psd_test_memory(buffer,len)) return stbi_psd_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_pic_test_memory(buffer,len)) return stbi_pic_load_from_memory(buffer,len,x,y,comp,req_comp); + stbi s; + start_mem(&s,buffer,len); + return stbi_load_main(&s,x,y,comp,req_comp); +} - #ifndef STBI_NO_HDR - if (stbi_hdr_test_memory(buffer, len)) { - float *hdr = stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); - return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); - } - #endif - - for (i=0; i < max_loaders; ++i) - if (loaders[i]->test_memory(buffer,len)) - return loaders[i]->load_from_memory(buffer,len,x,y,comp,req_comp); - // test tga last because it's a crappy test! - if (stbi_tga_test_memory(buffer,len)) - return stbi_tga_load_from_memory(buffer,len,x,y,comp,req_comp); - return epuc("unknown image type", "Image not of any known type, or corrupt"); +unsigned char *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_load_main(&s,x,y,comp,req_comp); } #ifndef STBI_NO_HDR +float *stbi_loadf_main(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi_hdr_test(s)) + return stbi_hdr_load(s,x,y,comp,req_comp); + #endif + data = stbi_load_main(s, x, y, comp, req_comp); + if (data) + return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return epf("unknown image type", "Image not of any known type, or corrupt"); +} + +float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer,len); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + +float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + #ifndef STBI_NO_STDIO float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) { @@ -697,31 +649,13 @@ float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { - unsigned char *data; - #ifndef STBI_NO_HDR - if (stbi_hdr_test_file(f)) - return stbi_hdr_load_from_file(f,x,y,comp,req_comp); - #endif - data = stbi_load_from_file(f, x, y, comp, req_comp); - if (data) - return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); - return epf("unknown image type", "Image not of any known type, or corrupt"); + stbi s; + start_file(&s,f); + return stbi_loadf_main(&s,x,y,comp,req_comp); } -#endif +#endif // !STBI_NO_STDIO -float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *data; - #ifndef STBI_NO_HDR - if (stbi_hdr_test_memory(buffer, len)) - return stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); - #endif - data = stbi_load_from_memory(buffer, len, x, y, comp, req_comp); - if (data) - return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); - return epf("unknown image type", "Image not of any known type, or corrupt"); -} -#endif +#endif // !STBI_NO_HDR // these is-hdr-or-not is defined independent of whether STBI_NO_HDR is // defined, for API simplicity; if STBI_NO_HDR is defined, it always @@ -730,8 +664,12 @@ float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, in int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) { #ifndef STBI_NO_HDR - return stbi_hdr_test_memory(buffer, len); + stbi s; + start_mem(&s,buffer,len); + return stbi_hdr_test(&s); #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); return 0; #endif } @@ -751,13 +689,25 @@ extern int stbi_is_hdr (char const *filename) extern int stbi_is_hdr_from_file(FILE *f) { #ifndef STBI_NO_HDR - return stbi_hdr_test_file(f); + stbi s; + start_file(&s,f); + return stbi_hdr_test(&s); #else return 0; #endif } +#endif // !STBI_NO_STDIO -#endif +extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_hdr_test(&s); + #else + return 0; + #endif +} #ifndef STBI_NO_HDR static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f; @@ -780,119 +730,82 @@ enum { SCAN_load=0, SCAN_type, - SCAN_header, + SCAN_header }; -typedef struct -{ - uint32 img_x, img_y; - int img_n, img_out_n; - - #ifndef STBI_NO_STDIO - FILE *img_file; - int buflen; - uint8 buffer_start[128]; - int from_file; - #endif - uint8 *img_buffer, *img_buffer_end; -} stbi; - -#ifndef STBI_NO_STDIO -static void start_file(stbi *s, FILE *f) -{ - s->img_file = f; - s->buflen = sizeof(s->buffer_start); - s->img_buffer_end = s->buffer_start + s->buflen; - s->img_buffer = s->img_buffer_end; - s->from_file = 1; -} -#endif - -static void start_mem(stbi *s, uint8 const *buffer, int len) -{ -#ifndef STBI_NO_STDIO - s->img_file = NULL; - s->from_file = 0; -#endif - s->img_buffer = (uint8 *) buffer; - s->img_buffer_end = (uint8 *) buffer+len; -} - -#ifndef STBI_NO_STDIO static void refill_buffer(stbi *s) { - int n = fread(s->buffer_start, 1, s->buflen, s->img_file); + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); if (n == 0) { - s->from_file = 0; - s->img_buffer = s->img_buffer_end-1; + // 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; } } -#endif -__forceinline static int get8(stbi *s) +stbi_inline static int get8(stbi *s) { if (s->img_buffer < s->img_buffer_end) return *s->img_buffer++; -#ifndef STBI_NO_STDIO - if (s->from_file) { + if (s->read_from_callbacks) { refill_buffer(s); return *s->img_buffer++; } -#endif return 0; } -__forceinline static int at_eof(stbi *s) +stbi_inline static int at_eof(stbi *s) { -#ifndef STBI_NO_STDIO - if (s->img_file) { - if (!feof(s->img_file)) return 0; + 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->from_file == 0) return 1; + if (s->read_from_callbacks == 0) return 1; } -#endif - return s->img_buffer >= s->img_buffer_end; + + return s->img_buffer >= s->img_buffer_end; } -__forceinline static uint8 get8u(stbi *s) +stbi_inline static stbi__uint8 get8u(stbi *s) { - return (uint8) get8(s); + return (stbi__uint8) get8(s); } static void skip(stbi *s, int n) { -#ifndef STBI_NO_STDIO - if (s->img_file) { - int blen = s->img_buffer_end - s->img_buffer; + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { s->img_buffer = s->img_buffer_end; - fseek(s->img_file, n - blen, SEEK_CUR); + (s->io.skip)(s->io_user_data, n - blen); return; } } -#endif s->img_buffer += n; } static int getn(stbi *s, stbi_uc *buffer, int n) { -#ifndef STBI_NO_STDIO - if (s->img_file) { - int blen = s->img_buffer_end - s->img_buffer; + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { - int res; + int res, count; + memcpy(buffer, s->img_buffer, blen); - res = ((int) fread(buffer + blen, 1, n - blen, s->img_file) == (n-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; } } -#endif + if (s->img_buffer+n <= s->img_buffer_end) { memcpy(buffer, s->img_buffer, n); s->img_buffer += n; @@ -907,9 +820,9 @@ static int get16(stbi *s) return (z << 8) + get8(s); } -static uint32 get32(stbi *s) +static stbi__uint32 get32(stbi *s) { - uint32 z = get16(s); + stbi__uint32 z = get16(s); return (z << 16) + get16(s); } @@ -919,9 +832,9 @@ static int get16le(stbi *s) return z + (get8(s) << 8); } -static uint32 get32le(stbi *s) +static stbi__uint32 get32le(stbi *s) { - uint32 z = get16le(s); + stbi__uint32 z = get16le(s); return z + (get16le(s) << 16); } @@ -936,12 +849,12 @@ static uint32 get32le(stbi *s) // assume data buffer is malloced, so malloc a new one and free that one // only failure mode is malloc failing -static uint8 compute_y(int r, int g, int b) +static stbi__uint8 compute_y(int r, int g, int b) { - return (uint8) (((r*77) + (g*150) + (29*b)) >> 8); + return (stbi__uint8) (((r*77) + (g*150) + (29*b)) >> 8); } -static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, uint x, uint y) +static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; unsigned char *good; @@ -1016,13 +929,13 @@ static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp) float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f; if (z < 0) z = 0; if (z > 255) z = 255; - output[i*comp + k] = (uint8) float2int(z); + output[i*comp + k] = (stbi__uint8) 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] = (uint8) float2int(z); + output[i*comp + k] = (stbi__uint8) float2int(z); } } free(data); @@ -1062,24 +975,24 @@ static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp) typedef struct { - uint8 fast[1 << FAST_BITS]; + stbi__uint8 fast[1 << FAST_BITS]; // weirdly, repacking this into AoS is a 10% speed loss, instead of a win - uint16 code[256]; - uint8 values[256]; - uint8 size[257]; + stbi__uint16 code[256]; + stbi__uint8 values[256]; + stbi__uint8 size[257]; unsigned int maxcode[18]; int delta[17]; // old 'firstsymbol' - old 'firstcode' } huffman; typedef struct { - #if STBI_SIMD + #ifdef STBI_SIMD unsigned short dequant2[4][64]; #endif - stbi s; + stbi *s; huffman huff_dc[4]; huffman huff_ac[4]; - uint8 dequant[4][64]; + stbi__uint8 dequant[4][64]; // sizes for components, interleaved MCUs int img_h_max, img_v_max; @@ -1096,12 +1009,12 @@ typedef struct int dc_pred; int x,y,w2,h2; - uint8 *data; + stbi__uint8 *data; void *raw_data; - uint8 *linebuf; + stbi__uint8 *linebuf; } img_comp[4]; - uint32 code_buffer; // jpeg entropy-coded buffer + 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 @@ -1116,7 +1029,7 @@ static int build_huffman(huffman *h, int *count) // 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++] = (uint8) (i+1); + h->size[k++] = (stbi__uint8) (i+1); h->size[k] = 0; // compute actual symbols (from jpeg spec) @@ -1127,7 +1040,7 @@ static int build_huffman(huffman *h, int *count) h->delta[j] = k - code; if (h->size[k] == j) { while (h->size[k] == j) - h->code[k++] = (uint16) (code++); + h->code[k++] = (stbi__uint16) (code++); if (code-1 >= (1 << j)) return e("bad code lengths","Corrupt JPEG"); } // compute largest code + 1 for this size, preshifted as needed later @@ -1144,7 +1057,7 @@ static int build_huffman(huffman *h, int *count) int c = h->code[i] << (FAST_BITS-s); int m = 1 << (FAST_BITS-s); for (j=0; j < m; ++j) { - h->fast[c+j] = (uint8) i; + h->fast[c+j] = (stbi__uint8) i; } } } @@ -1154,9 +1067,9 @@ static int build_huffman(huffman *h, int *count) static void grow_buffer_unsafe(jpeg *j) { do { - int b = j->nomore ? 0 : get8(&j->s); + int b = j->nomore ? 0 : get8(j->s); if (b == 0xff) { - int c = get8(&j->s); + int c = get8(j->s); if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; @@ -1169,10 +1082,10 @@ static void grow_buffer_unsafe(jpeg *j) } // (1 << n) - 1 -static uint32 bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; +static stbi__uint32 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 -__forceinline static int decode(jpeg *j, huffman *h) +stbi_inline static int decode(jpeg *j, huffman *h) { unsigned int temp; int c,k; @@ -1223,7 +1136,7 @@ __forceinline static int decode(jpeg *j, huffman *h) // combined JPEG 'receive' and JPEG 'extend', since baseline // always extends everything it receives. -__forceinline static int extend_receive(jpeg *j, int n) +stbi_inline static int extend_receive(jpeg *j, int n) { unsigned int m = 1 << (n-1); unsigned int k; @@ -1250,7 +1163,7 @@ __forceinline static int extend_receive(jpeg *j, int n) // 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 uint8 dezigzag[64+15] = +static stbi__uint8 dezigzag[64+15] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, @@ -1301,14 +1214,14 @@ static int decode_block(jpeg *j, short data[64], huffman *hdc, huffman *hac, int } // take a -128..127 value and clamp it and convert to 0..255 -__forceinline static uint8 clamp(int x) +stbi_inline static stbi__uint8 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 (uint8) x; + return (stbi__uint8) x; } #define f2f(x) (int) (((x) * 4096 + 0.5)) @@ -1352,18 +1265,18 @@ __forceinline static uint8 clamp(int x) t1 += p2+p4; \ t0 += p1+p3; -#if STBI_SIMD +#ifdef STBI_SIMD typedef unsigned short stbi_dequantize_t; #else -typedef uint8 stbi_dequantize_t; +typedef stbi__uint8 stbi_dequantize_t; #endif // .344 seconds on 3*anemones.jpg -static void idct_block(uint8 *out, int out_stride, short data[64], stbi_dequantize_t *dequantize) +static void idct_block(stbi__uint8 *out, int out_stride, short data[64], stbi_dequantize_t *dequantize) { int i,val[64],*v=val; stbi_dequantize_t *dq = dequantize; - uint8 *o; + stbi__uint8 *o; short *d = data; // columns @@ -1423,7 +1336,7 @@ static void idct_block(uint8 *out, int out_stride, short data[64], stbi_dequanti #ifdef STBI_SIMD static stbi_idct_8x8 stbi_idct_installed = idct_block; -extern void stbi_install_idct(stbi_idct_8x8 func) +void stbi_install_idct(stbi_idct_8x8 func) { stbi_idct_installed = func; } @@ -1433,14 +1346,14 @@ extern void stbi_install_idct(stbi_idct_8x8 func) // 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 uint8 get_marker(jpeg *j) +static stbi__uint8 get_marker(jpeg *j) { - uint8 x; + stbi__uint8 x; if (j->marker != MARKER_none) { x = j->marker; j->marker = MARKER_none; return x; } - x = get8u(&j->s); + x = get8u(j->s); if (x != 0xff) return MARKER_none; while (x == 0xff) - x = get8u(&j->s); + x = get8u(j->s); return x; } @@ -1467,7 +1380,7 @@ static int parse_entropy_coded_data(jpeg *z) reset(z); if (z->scan_n == 1) { int i,j; - #if STBI_SIMD + #ifdef STBI_SIMD __declspec(align(16)) #endif short data[64]; @@ -1481,7 +1394,7 @@ static int parse_entropy_coded_data(jpeg *z) for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; - #if STBI_SIMD + #ifdef STBI_SIMD stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); #else idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); @@ -1511,7 +1424,7 @@ static int parse_entropy_coded_data(jpeg *z) int x2 = (i*z->img_comp[n].h + x)*8; int y2 = (j*z->img_comp[n].v + y)*8; if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; - #if STBI_SIMD + #ifdef STBI_SIMD stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); #else idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); @@ -1545,21 +1458,21 @@ static int process_marker(jpeg *z, int m) return e("progressive jpeg","JPEG format not supported (progressive)"); case 0xDD: // DRI - specify restart interval - if (get16(&z->s) != 4) return e("bad DRI len","Corrupt JPEG"); - z->restart_interval = get16(&z->s); + if (get16(z->s) != 4) return e("bad DRI len","Corrupt JPEG"); + z->restart_interval = get16(z->s); return 1; case 0xDB: // DQT - define quantization table - L = get16(&z->s)-2; + L = get16(z->s)-2; while (L > 0) { - int q = get8(&z->s); + int q = get8(z->s); int p = q >> 4; int t = q & 15,i; if (p != 0) return e("bad DQT type","Corrupt JPEG"); if (t > 3) return e("bad DQT table","Corrupt JPEG"); for (i=0; i < 64; ++i) - z->dequant[t][dezigzag[i]] = get8u(&z->s); - #if STBI_SIMD + z->dequant[t][dezigzag[i]] = get8u(z->s); + #ifdef STBI_SIMD for (i=0; i < 64; ++i) z->dequant2[t][i] = z->dequant[t][i]; #endif @@ -1568,17 +1481,17 @@ static int process_marker(jpeg *z, int m) return L==0; case 0xC4: // DHT - define huffman table - L = get16(&z->s)-2; + L = get16(z->s)-2; while (L > 0) { - uint8 *v; - int sizes[16],i,m=0; - int q = get8(&z->s); + stbi__uint8 *v; + int sizes[16],i,n=0; + int q = get8(z->s); int tc = q >> 4; int th = q & 15; if (tc > 1 || th > 3) return e("bad DHT header","Corrupt JPEG"); for (i=0; i < 16; ++i) { - sizes[i] = get8(&z->s); - m += sizes[i]; + sizes[i] = get8(z->s); + n += sizes[i]; } L -= 17; if (tc == 0) { @@ -1588,15 +1501,15 @@ static int process_marker(jpeg *z, int m) if (!build_huffman(z->huff_ac+th, sizes)) return 0; v = z->huff_ac[th].values; } - for (i=0; i < m; ++i) - v[i] = get8u(&z->s); - L -= m; + for (i=0; i < n; ++i) + v[i] = get8u(z->s); + L -= n; } return L==0; } // check for comment block or APP blocks if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - skip(&z->s, get16(&z->s)-2); + skip(z->s, get16(z->s)-2); return 1; } return 0; @@ -1606,31 +1519,31 @@ static int process_marker(jpeg *z, int m) static int process_scan_header(jpeg *z) { int i; - int Ls = get16(&z->s); - z->scan_n = get8(&z->s); - if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s.img_n) return e("bad SOS component count","Corrupt JPEG"); + int Ls = get16(z->s); + z->scan_n = get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return e("bad SOS component count","Corrupt JPEG"); if (Ls != 6+2*z->scan_n) return e("bad SOS len","Corrupt JPEG"); for (i=0; i < z->scan_n; ++i) { - int id = get8(&z->s), which; - int q = get8(&z->s); - for (which = 0; which < z->s.img_n; ++which) + int id = get8(z->s), which; + int q = 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; + if (which == z->s->img_n) return 0; z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return e("bad DC huff","Corrupt JPEG"); z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return e("bad AC huff","Corrupt JPEG"); z->order[i] = which; } - if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); - get8(&z->s); // should be 63, but might be 0 - if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); + if (get8(z->s) != 0) return e("bad SOS","Corrupt JPEG"); + get8(z->s); // should be 63, but might be 0 + if (get8(z->s) != 0) return e("bad SOS","Corrupt JPEG"); return 1; } static int process_frame_header(jpeg *z, int scan) { - stbi *s = &z->s; + stbi *s = z->s; int Lf,p,i,q, h_max=1,v_max=1,c; Lf = get16(s); if (Lf < 11) return e("bad SOF len","Corrupt JPEG"); // JPEG p = get8(s); if (p != 8) return e("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline @@ -1693,7 +1606,7 @@ static int process_frame_header(jpeg *z, int scan) return e("outofmem", "Out of memory"); } // align blocks for installable-idct using mmx/sse - z->img_comp[i].data = (uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].data = (stbi__uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); z->img_comp[i].linebuf = NULL; } @@ -1720,7 +1633,7 @@ static int decode_jpeg_header(jpeg *z, int scan) m = get_marker(z); while (m == MARKER_none) { // some files have extra padding after their blocks, so ok, we'll scan - if (at_eof(&z->s)) return e("no SOF", "Corrupt JPEG"); + if (at_eof(z->s)) return e("no SOF", "Corrupt JPEG"); m = get_marker(z); } } @@ -1740,10 +1653,10 @@ static int decode_jpeg_image(jpeg *j) if (!parse_entropy_coded_data(j)) return 0; if (j->marker == MARKER_none ) { // handle 0s at the end of image data from IP Kamera 9060 - while (!at_eof(&j->s)) { - int x = get8(&j->s); + while (!at_eof(j->s)) { + int x = get8(j->s); if (x == 255) { - j->marker = get8u(&j->s); + j->marker = get8u(j->s); break; } else if (x != 0) { return 0; @@ -1761,12 +1674,12 @@ static int decode_jpeg_image(jpeg *j) // static jfif-centered resampling (across block boundaries) -typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1, +typedef stbi__uint8 *(*resample_row_func)(stbi__uint8 *out, stbi__uint8 *in0, stbi__uint8 *in1, int w, int hs); -#define div4(x) ((uint8) ((x) >> 2)) +#define div4(x) ((stbi__uint8) ((x) >> 2)) -static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +static stbi__uint8 *resample_row_1(stbi__uint8 *out, stbi__uint8 *in_near, stbi__uint8 *in_far, int w, int hs) { STBI_NOTUSED(out); STBI_NOTUSED(in_far); @@ -1775,7 +1688,7 @@ static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, i return in_near; } -static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +static stbi__uint8* resample_row_v_2(stbi__uint8 *out, stbi__uint8 *in_near, stbi__uint8 *in_far, int w, int hs) { // need to generate two samples vertically for every one in input int i; @@ -1785,11 +1698,11 @@ static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, return out; } -static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +static stbi__uint8* resample_row_h_2(stbi__uint8 *out, stbi__uint8 *in_near, stbi__uint8 *in_far, int w, int hs) { // need to generate two samples horizontally for every one in input int i; - uint8 *input = in_near; + stbi__uint8 *input = in_near; if (w == 1) { // if only one sample, can't do any interpolation @@ -1813,9 +1726,9 @@ static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w return out; } -#define div16(x) ((uint8) ((x) >> 4)) +#define div16(x) ((stbi__uint8) ((x) >> 4)) -static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +static stbi__uint8 *resample_row_hv_2(stbi__uint8 *out, stbi__uint8 *in_near, stbi__uint8 *in_far, int w, int hs) { // need to generate 2x2 samples for every one in input int i,t0,t1; @@ -1839,11 +1752,11 @@ static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w return out; } -static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +static stbi__uint8 *resample_row_generic(stbi__uint8 *out, stbi__uint8 *in_near, stbi__uint8 *in_far, int w, int hs) { // resample with nearest-neighbor int i,j; - in_far = in_far; + STBI_NOTUSED(in_far); for (i=0; i < w; ++i) for (j=0; j < hs; ++j) out[i*hs+j] = in_near[i]; @@ -1854,7 +1767,7 @@ static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, in // 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro) // VC6 without processor=Pro is generating multiple LEAs per multiply! -static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const uint8 *pcr, int count, int step) +static void YCbCr_to_RGB_row(stbi__uint8 *out, const stbi__uint8 *y, const stbi__uint8 *pcb, const stbi__uint8 *pcr, int count, int step) { int i; for (i=0; i < count; ++i) { @@ -1871,15 +1784,15 @@ static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const 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] = (uint8)r; - out[1] = (uint8)g; - out[2] = (uint8)b; + out[0] = (stbi__uint8)r; + out[1] = (stbi__uint8)g; + out[2] = (stbi__uint8)b; out[3] = 255; out += step; } } -#if STBI_SIMD +#ifdef STBI_SIMD static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row; void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) @@ -1893,7 +1806,7 @@ void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) static void cleanup_jpeg(jpeg *j) { int i; - for (i=0; i < j->s.img_n; ++i) { + for (i=0; i < j->s->img_n; ++i) { if (j->img_comp[i].data) { free(j->img_comp[i].raw_data); j->img_comp[i].data = NULL; @@ -1908,37 +1821,37 @@ static void cleanup_jpeg(jpeg *j) typedef struct { resample_row_func resample; - uint8 *line0,*line1; + stbi__uint8 *line0,*line1; int hs,vs; // expansion factor in each axis - int w_lores; // horizontal pixels pre-expansion + 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; -static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +static stbi__uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { int n, decode_n; // validate req_comp if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); - z->s.img_n = 0; + z->s->img_n = 0; // load a jpeg image from whichever source if (!decode_jpeg_image(z)) { cleanup_jpeg(z); return NULL; } // determine actual number of components to generate - n = req_comp ? req_comp : z->s.img_n; + n = req_comp ? req_comp : z->s->img_n; - if (z->s.img_n == 3 && n < 3) + if (z->s->img_n == 3 && n < 3) decode_n = 1; else - decode_n = z->s.img_n; + decode_n = z->s->img_n; // resample and color-convert { int k; - uint i,j; - uint8 *output; - uint8 *coutput[4]; + unsigned int i,j; + stbi__uint8 *output; + stbi__uint8 *coutput[4]; stbi_resample res_comp[4]; @@ -1947,13 +1860,13 @@ static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int re // allocate line buffer big enough for upsampling off the edges // with upsample factor of 4 - z->img_comp[k].linebuf = (uint8 *) malloc(z->s.img_x + 3); + z->img_comp[k].linebuf = (stbi__uint8 *) malloc(z->s->img_x + 3); if (!z->img_comp[k].linebuf) { cleanup_jpeg(z); return epuc("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->w_lores = (z->s->img_x + r->hs-1) / r->hs; r->ypos = 0; r->line0 = r->line1 = z->img_comp[k].data; @@ -1965,12 +1878,12 @@ static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int re } // can't error after this so, this is safe - output = (uint8 *) malloc(n * z->s.img_x * z->s.img_y + 1); + output = (stbi__uint8 *) malloc(n * z->s->img_x * z->s->img_y + 1); if (!output) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } // now go ahead and resample - for (j=0; j < z->s.img_y; ++j) { - uint8 *out = output + n * z->s.img_x * j; + for (j=0; j < z->s->img_y; ++j) { + stbi__uint8 *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); @@ -1986,125 +1899,71 @@ static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int re } } if (n >= 3) { - uint8 *y = coutput[0]; - if (z->s.img_n == 3) { - #if STBI_SIMD - stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n); + stbi__uint8 *y = coutput[0]; + if (z->s->img_n == 3) { + #ifdef STBI_SIMD + stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s->img_x, n); #else - YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s.img_x, n); + YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s->img_x, n); #endif } else - for (i=0; i < z->s.img_x; ++i) { + 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 { - uint8 *y = coutput[0]; + stbi__uint8 *y = coutput[0]; if (n == 1) - for (i=0; i < z->s.img_x; ++i) out[i] = y[i]; + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; else - for (i=0; i < z->s.img_x; ++i) *out++ = y[i], *out++ = 255; + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; } } cleanup_jpeg(z); - *out_x = z->s.img_x; - *out_y = z->s.img_y; - if (comp) *comp = z->s.img_n; // report original components, not output + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n; // report original components, not output return output; } } -#ifndef STBI_NO_STDIO -unsigned char *stbi_jpeg_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +static unsigned char *stbi_jpeg_load(stbi *s, int *x, int *y, int *comp, int req_comp) { jpeg j; - start_file(&j.s, f); + j.s = s; return load_jpeg_image(&j, x,y,comp,req_comp); } -unsigned char *stbi_jpeg_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_jpeg_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return data; -} -#endif - -unsigned char *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +static int stbi_jpeg_test(stbi *s) { + int r; jpeg j; - start_mem(&j.s, buffer,len); - return load_jpeg_image(&j, x,y,comp,req_comp); + j.s = s; + r = decode_jpeg_header(&j, SCAN_type); + stbi_rewind(s); + return r; } static int stbi_jpeg_info_raw(jpeg *j, int *x, int *y, int *comp) { - if (!decode_jpeg_header(j, SCAN_header)) + if (!decode_jpeg_header(j, 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; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n; return 1; } -#ifndef STBI_NO_STDIO -int stbi_jpeg_test_file(FILE *f) -{ - int n,r; - jpeg j; - n = ftell(f); - start_file(&j.s, f); - r = decode_jpeg_header(&j, SCAN_type); - fseek(f,n,SEEK_SET); - return r; -} - -int stbi_jpeg_info_from_file(FILE *f, int *x, int *y, int *comp) -{ - jpeg j; - long n = ftell(f); - int res; - start_file(&j.s, f); - res = stbi_jpeg_info_raw(&j, x, y, comp); - fseek(f, n, SEEK_SET); - return res; -} - -int stbi_jpeg_info(char const *filename, int *x, int *y, int *comp) -{ - FILE *f = fopen(filename, "rb"); - int result; - if (!f) return e("can't fopen", "Unable to open file"); - result = stbi_jpeg_info_from_file(f, x, y, comp); - fclose(f); - return result; -} -#endif - -int stbi_jpeg_test_memory(stbi_uc const *buffer, int len) +static int stbi_jpeg_info(stbi *s, int *x, int *y, int *comp) { jpeg j; - start_mem(&j.s, buffer,len); - return decode_jpeg_header(&j, SCAN_type); + j.s = s; + return stbi_jpeg_info_raw(&j, x, y, comp); } -int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) -{ - jpeg j; - start_mem(&j.s, buffer, len); - return stbi_jpeg_info_raw(&j, x, y, comp); -} - -#ifndef STBI_NO_STDIO -extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif -extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); - // public domain zlib decode v0.2 Sean Barrett 2006-11-18 // simple implementation // - all input must be provided in an upfront buffer @@ -2120,15 +1979,15 @@ extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int * // (jpegs packs from left, zlib from right, so can't share code) typedef struct { - uint16 fast[1 << ZFAST_BITS]; - uint16 firstcode[16]; + stbi__uint16 fast[1 << ZFAST_BITS]; + stbi__uint16 firstcode[16]; int maxcode[17]; - uint16 firstsymbol[16]; - uint8 size[288]; - uint16 value[288]; + stbi__uint16 firstsymbol[16]; + stbi__uint8 size[288]; + stbi__uint16 value[288]; } zhuffman; -__forceinline static int bitreverse16(int n) +stbi_inline static int bitreverse16(int n) { n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); @@ -2137,7 +1996,7 @@ __forceinline static int bitreverse16(int n) return n; } -__forceinline static int bit_reverse(int v, int bits) +stbi_inline static int bit_reverse(int v, int bits) { assert(bits <= 16); // to bit reverse n bits, reverse 16 and shift @@ -2145,7 +2004,7 @@ __forceinline static int bit_reverse(int v, int bits) return bitreverse16(v) >> (16-bits); } -static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) +static int zbuild_huffman(zhuffman *z, stbi__uint8 *sizelist, int num) { int i,k=0; int code, next_code[16], sizes[17]; @@ -2153,7 +2012,7 @@ static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) // DEFLATE spec for generating codes memset(sizes, 0, sizeof(sizes)); memset(z->fast, 255, sizeof(z->fast)); - for (i=0; i < num; ++i) + for (i=0; i < num; ++i) ++sizes[sizelist[i]]; sizes[0] = 0; for (i=1; i < 16; ++i) @@ -2161,8 +2020,8 @@ static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) code = 0; for (i=1; i < 16; ++i) { next_code[i] = code; - z->firstcode[i] = (uint16) code; - z->firstsymbol[i] = (uint16) k; + 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 e("bad codelengths","Corrupt JPEG"); @@ -2175,12 +2034,12 @@ static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) int s = sizelist[i]; if (s) { int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; - z->size[c] = (uint8)s; - z->value[c] = (uint16)i; + z->size[c] = (stbi__uint8)s; + z->value[c] = (stbi__uint16)i; if (s <= ZFAST_BITS) { int k = bit_reverse(next_code[s],s); while (k < (1 << ZFAST_BITS)) { - z->fast[k] = (uint16) c; + z->fast[k] = (stbi__uint16) c; k += (1 << s); } } @@ -2198,9 +2057,9 @@ static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) typedef struct { - uint8 *zbuffer, *zbuffer_end; + stbi__uint8 *zbuffer, *zbuffer_end; int num_bits; - uint32 code_buffer; + stbi__uint32 code_buffer; char *zout; char *zout_start; @@ -2210,7 +2069,7 @@ typedef struct zhuffman z_length, z_distance; } zbuf; -__forceinline static int zget8(zbuf *z) +stbi_inline static int zget8(zbuf *z) { if (z->zbuffer >= z->zbuffer_end) return 0; return *z->zbuffer++; @@ -2225,17 +2084,17 @@ static void fill_bits(zbuf *z) } while (z->num_bits <= 24); } -__forceinline static unsigned int zreceive(zbuf *z, int n) +stbi_inline static unsigned int zreceive(zbuf *z, int n) { unsigned int k; if (z->num_bits < n) fill_bits(z); k = z->code_buffer & ((1 << n) - 1); z->code_buffer >>= n; z->num_bits -= n; - return k; + return k; } -__forceinline static int zhuffman_decode(zbuf *a, zhuffman *z) +stbi_inline static int zhuffman_decode(zbuf *a, zhuffman *z) { int b,s,k; if (a->num_bits < 16) fill_bits(a); @@ -2284,7 +2143,7 @@ static int length_base[31] = { 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; -static int length_extra[31]= +static int length_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 int dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, @@ -2302,7 +2161,7 @@ static int parse_huffman_block(zbuf *a) if (a->zout >= a->zout_end) if (!expand(a, 1)) return 0; *a->zout++ = (char) z; } else { - uint8 *p; + stbi__uint8 *p; int len,dist; if (z == 256) return 1; z -= 257; @@ -2314,7 +2173,7 @@ static int parse_huffman_block(zbuf *a) if (dist_extra[z]) dist += zreceive(a, dist_extra[z]); if (a->zout - a->zout_start < dist) return e("bad dist","Corrupt PNG"); if (a->zout + len > a->zout_end) if (!expand(a, len)) return 0; - p = (uint8 *) (a->zout - dist); + p = (stbi__uint8 *) (a->zout - dist); while (len--) *a->zout++ = *p++; } @@ -2323,10 +2182,10 @@ static int parse_huffman_block(zbuf *a) static int compute_huffman_codes(zbuf *a) { - static uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + static stbi__uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; zhuffman z_codelength; - uint8 lencodes[286+32+137];//padding for maximum single op - uint8 codelength_sizes[19]; + stbi__uint8 lencodes[286+32+137];//padding for maximum single op + stbi__uint8 codelength_sizes[19]; int i,n; int hlit = zreceive(a,5) + 257; @@ -2336,7 +2195,7 @@ static int compute_huffman_codes(zbuf *a) memset(codelength_sizes, 0, sizeof(codelength_sizes)); for (i=0; i < hclen; ++i) { int s = zreceive(a,3); - codelength_sizes[length_dezigzag[i]] = (uint8) s; + codelength_sizes[length_dezigzag[i]] = (stbi__uint8) s; } if (!zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; @@ -2345,7 +2204,7 @@ static int compute_huffman_codes(zbuf *a) int c = zhuffman_decode(a, &z_codelength); assert(c >= 0 && c < 19); if (c < 16) - lencodes[n++] = (uint8) c; + lencodes[n++] = (stbi__uint8) c; else if (c == 16) { c = zreceive(a,2)+3; memset(lencodes+n, lencodes[n-1], c); @@ -2369,21 +2228,21 @@ static int compute_huffman_codes(zbuf *a) static int parse_uncompressed_block(zbuf *a) { - uint8 header[4]; + stbi__uint8 header[4]; int len,nlen,k; if (a->num_bits & 7) zreceive(a, a->num_bits & 7); // discard // drain the bit-packed data into header k = 0; while (a->num_bits > 0) { - header[k++] = (uint8) (a->code_buffer & 255); // wtf this warns? + header[k++] = (stbi__uint8) (a->code_buffer & 255); // wtf this warns? a->code_buffer >>= 8; a->num_bits -= 8; } assert(a->num_bits == 0); // now fill header the normal way while (k < 4) - header[k++] = (uint8) zget8(a); + header[k++] = (stbi__uint8) zget8(a); len = header[1] * 256 + header[0]; nlen = header[3] * 256 + header[2]; if (nlen != (len ^ 0xffff)) return e("zlib corrupt","Corrupt PNG"); @@ -2410,7 +2269,7 @@ static int parse_zlib_header(zbuf *a) } // @TODO: should statically initialize these for optimal thread safety -static uint8 default_length[288], default_distance[32]; +static stbi__uint8 default_length[288], default_distance[32]; static void init_defaults(void) { int i; // use <= to match clearly with spec @@ -2469,8 +2328,8 @@ char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial zbuf a; char *p = (char *) malloc(initial_size); if (p == NULL) return NULL; - a.zbuffer = (uint8 *) buffer; - a.zbuffer_end = (uint8 *) buffer + len; + a.zbuffer = (stbi__uint8 *) buffer; + a.zbuffer_end = (stbi__uint8 *) buffer + len; if (do_zlib(&a, p, initial_size, 1, 1)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; @@ -2490,8 +2349,8 @@ char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, zbuf a; char *p = (char *) malloc(initial_size); if (p == NULL) return NULL; - a.zbuffer = (uint8 *) buffer; - a.zbuffer_end = (uint8 *) buffer + len; + a.zbuffer = (stbi__uint8 *) buffer; + a.zbuffer_end = (stbi__uint8 *) buffer + len; if (do_zlib(&a, p, initial_size, 1, parse_header)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; @@ -2504,8 +2363,8 @@ char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) { zbuf a; - a.zbuffer = (uint8 *) ibuffer; - a.zbuffer_end = (uint8 *) ibuffer + ilen; + a.zbuffer = (stbi__uint8 *) ibuffer; + a.zbuffer_end = (stbi__uint8 *) ibuffer + ilen; if (do_zlib(&a, obuffer, olen, 0, 1)) return (int) (a.zout - a.zout_start); else @@ -2517,8 +2376,8 @@ char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) zbuf a; char *p = (char *) malloc(16384); if (p == NULL) return NULL; - a.zbuffer = (uint8 *) buffer; - a.zbuffer_end = (uint8 *) buffer+len; + a.zbuffer = (stbi__uint8 *) buffer; + a.zbuffer_end = (stbi__uint8 *) buffer+len; if (do_zlib(&a, p, 16384, 1, 0)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; @@ -2531,8 +2390,8 @@ char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) { zbuf a; - a.zbuffer = (uint8 *) ibuffer; - a.zbuffer_end = (uint8 *) ibuffer + ilen; + a.zbuffer = (stbi__uint8 *) ibuffer; + a.zbuffer_end = (stbi__uint8 *) ibuffer + ilen; if (do_zlib(&a, obuffer, olen, 0, 0)) return (int) (a.zout - a.zout_start); else @@ -2552,8 +2411,8 @@ int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffe typedef struct { - uint32 length; - uint32 type; + stbi__uint32 length; + stbi__uint32 type; } chunk; #define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) @@ -2568,26 +2427,26 @@ static chunk get_chunk_header(stbi *s) static int check_png_header(stbi *s) { - static uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 }; + static stbi__uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 }; int i; for (i=0; i < 8; ++i) - if (get8(s) != png_sig[i]) return e("bad png sig","Not a PNG"); + if (get8u(s) != png_sig[i]) return e("bad png sig","Not a PNG"); return 1; } typedef struct { - stbi s; - uint8 *idata, *expanded, *out; + stbi *s; + stbi__uint8 *idata, *expanded, *out; } png; enum { F_none=0, F_sub=1, F_up=2, F_avg=3, F_paeth=4, - F_avg_first, F_paeth_first, + F_avg_first, F_paeth_first }; -static uint8 first_row_filter[5] = +static stbi__uint8 first_row_filter[5] = { F_none, F_sub, F_none, F_avg_first, F_paeth_first }; @@ -2604,15 +2463,15 @@ static int paeth(int a, int b, int c) } // create the png data from post-deflated data -static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, uint32 x, uint32 y) +static int create_png_image_raw(png *a, stbi__uint8 *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y) { - stbi *s = &a->s; - uint32 i,j,stride = x*out_n; + stbi *s = a->s; + stbi__uint32 i,j,stride = x*out_n; int k; int img_n = s->img_n; // copy it into a local for later assert(out_n == s->img_n || out_n == s->img_n+1); if (stbi_png_partial) y = 1; - a->out = (uint8 *) malloc(x * y * out_n); + a->out = (stbi__uint8 *) malloc(x * y * out_n); if (!a->out) return e("outofmem", "Out of memory"); if (!stbi_png_partial) { if (s->img_x == x && s->img_y == y) { @@ -2622,8 +2481,8 @@ static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, u } } for (j=0; j < y; ++j) { - uint8 *cur = a->out + stride*j; - uint8 *prior = cur - stride; + stbi__uint8 *cur = a->out + stride*j; + stbi__uint8 *prior = cur - stride; int filter = *raw++; if (filter > 4) return e("invalid filter","Corrupt PNG"); // if first row, use special filter that doesn't sample previous row @@ -2635,7 +2494,7 @@ static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, u case F_sub : cur[k] = raw[k]; break; case F_up : cur[k] = raw[k] + prior[k]; break; case F_avg : cur[k] = raw[k] + (prior[k]>>1); break; - case F_paeth : cur[k] = (uint8) (raw[k] + paeth(0,prior[k],0)); break; + case F_paeth : cur[k] = (stbi__uint8) (raw[k] + paeth(0,prior[k],0)); break; case F_avg_first : cur[k] = raw[k]; break; case F_paeth_first: cur[k] = raw[k]; break; } @@ -2655,9 +2514,9 @@ static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, u CASE(F_sub) cur[k] = raw[k] + cur[k-img_n]; break; CASE(F_up) cur[k] = raw[k] + prior[k]; break; CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-img_n])>>1); break; - CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; + CASE(F_paeth) cur[k] = (stbi__uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; CASE(F_avg_first) cur[k] = raw[k] + (cur[k-img_n] >> 1); break; - CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break; + CASE(F_paeth_first) cur[k] = (stbi__uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break; } #undef CASE } else { @@ -2671,9 +2530,9 @@ static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, u CASE(F_sub) cur[k] = raw[k] + cur[k-out_n]; break; CASE(F_up) cur[k] = raw[k] + prior[k]; break; CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-out_n])>>1); break; - CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(F_paeth) cur[k] = (stbi__uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; CASE(F_avg_first) cur[k] = raw[k] + (cur[k-out_n] >> 1); break; - CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break; + CASE(F_paeth_first) cur[k] = (stbi__uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break; } #undef CASE } @@ -2681,18 +2540,18 @@ static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, u return 1; } -static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced) +static int create_png_image(png *a, stbi__uint8 *raw, stbi__uint32 raw_len, int out_n, int interlaced) { - uint8 *final; + stbi__uint8 *final; int p; int save; if (!interlaced) - return create_png_image_raw(a, raw, raw_len, out_n, a->s.img_x, a->s.img_y); + return create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y); save = stbi_png_partial; stbi_png_partial = 0; // de-interlacing - final = (uint8 *) malloc(a->s.img_x * a->s.img_y * out_n); + final = (stbi__uint8 *) malloc(a->s->img_x * a->s->img_y * out_n); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; @@ -2700,8 +2559,8 @@ static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int i 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]; + 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) { if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) { free(final); @@ -2709,7 +2568,7 @@ static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int i } for (j=0; j < y; ++j) for (i=0; i < x; ++i) - memcpy(final + (j*yspc[p]+yorig[p])*a->s.img_x*out_n + (i*xspc[p]+xorig[p])*out_n, + memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n, a->out + (j*x+i)*out_n, out_n); free(a->out); raw += (x*out_n+1)*y; @@ -2722,11 +2581,11 @@ static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int i return 1; } -static int compute_transparency(png *z, uint8 tc[3], int out_n) +static int compute_transparency(png *z, stbi__uint8 tc[3], int out_n) { - stbi *s = &z->s; - uint32 i, pixel_count = s->img_x * s->img_y; - uint8 *p = z->out; + stbi *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint8 *p = z->out; // compute color-based transparency, assuming we've // already got 255 as the alpha value in the output @@ -2747,12 +2606,12 @@ static int compute_transparency(png *z, uint8 tc[3], int out_n) return 1; } -static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n) +static int expand_palette(png *a, stbi__uint8 *palette, int len, int pal_img_n) { - uint32 i, pixel_count = a->s.img_x * a->s.img_y; - uint8 *p, *temp_out, *orig = a->out; + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi__uint8 *p, *temp_out, *orig = a->out; - p = (uint8 *) malloc(pixel_count * pal_img_n); + p = (stbi__uint8 *) malloc(pixel_count * pal_img_n); if (p == NULL) return e("outofmem", "Out of memory"); // between here and free(out) below, exitting would leak @@ -2798,13 +2657,13 @@ void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) static void stbi_de_iphone(png *z) { - stbi *s = &z->s; - uint32 i, pixel_count = s->img_x * s->img_y; - uint8 *p = z->out; + stbi *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint8 *p = z->out; if (s->img_out_n == 3) { // convert bgr to rgb for (i=0; i < pixel_count; ++i) { - uint8 t = p[0]; + stbi__uint8 t = p[0]; p[0] = p[2]; p[2] = t; p += 3; @@ -2814,8 +2673,8 @@ static void stbi_de_iphone(png *z) if (stbi_unpremultiply_on_load) { // convert bgr to rgb and unpremultiply for (i=0; i < pixel_count; ++i) { - uint8 a = p[3]; - uint8 t = p[0]; + stbi__uint8 a = p[3]; + stbi__uint8 t = p[0]; if (a) { p[0] = p[2] * 255 / a; p[1] = p[1] * 255 / a; @@ -2823,13 +2682,13 @@ static void stbi_de_iphone(png *z) } else { p[0] = p[2]; p[2] = t; - } + } p += 4; } } else { // convert bgr to rgb for (i=0; i < pixel_count; ++i) { - uint8 t = p[0]; + stbi__uint8 t = p[0]; p[0] = p[2]; p[2] = t; p += 4; @@ -2840,11 +2699,15 @@ static void stbi_de_iphone(png *z) static int parse_png_file(png *z, int scan, int req_comp) { - uint8 palette[1024], pal_img_n=0; - uint8 has_trans=0, tc[3]; - uint32 ioff=0, idata_limit=0, i, pal_len=0; + stbi__uint8 palette[1024], pal_img_n=0; + stbi__uint8 has_trans=0, tc[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; int first=1,k,interlace=0, iphone=0; - stbi *s = &z->s; + stbi *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; if (!check_png_header(s)) return 0; @@ -2911,10 +2774,10 @@ static int parse_png_file(png *z, int scan, int req_comp) palette[i*4+3] = get8u(s); } else { if (!(s->img_n & 1)) return e("tRNS with alpha","Corrupt PNG"); - if (c.length != (uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG"); has_trans = 1; for (k=0; k < s->img_n; ++k) - tc[k] = (uint8) get16(s); // non 8-bit images will be larger + tc[k] = (stbi__uint8) get16(s); // non 8-bit images will be larger } break; } @@ -2924,11 +2787,11 @@ static int parse_png_file(png *z, int scan, int req_comp) if (pal_img_n && !pal_len) return e("no PLTE","Corrupt PNG"); if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } if (ioff + c.length > idata_limit) { - uint8 *p; + stbi__uint8 *p; if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; - p = (uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory"); + p = (stbi__uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory"); z->idata = p; } if (!getn(s, z->idata+ioff,c.length)) return e("outofdata","Corrupt PNG"); @@ -2937,11 +2800,11 @@ static int parse_png_file(png *z, int scan, int req_comp) } case PNG_TYPE('I','E','N','D'): { - uint32 raw_len; + stbi__uint32 raw_len; if (first) return e("first not IHDR", "Corrupt PNG"); if (scan != SCAN_load) return 1; if (z->idata == NULL) return e("no IDAT","Corrupt PNG"); - z->expanded = (uint8 *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, 16384, (int *) &raw_len, !iphone); + z->expanded = (stbi__uint8 *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, 16384, (int *) &raw_len, !iphone); if (z->expanded == NULL) return 0; // zlib should set error free(z->idata); z->idata = NULL; if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) @@ -2972,10 +2835,10 @@ static int parse_png_file(png *z, int scan, int req_comp) #ifndef STBI_NO_FAILURE_STRINGS // not threadsafe static char invalid_chunk[] = "XXXX chunk not known"; - invalid_chunk[0] = (uint8) (c.type >> 24); - invalid_chunk[1] = (uint8) (c.type >> 16); - invalid_chunk[2] = (uint8) (c.type >> 8); - invalid_chunk[3] = (uint8) (c.type >> 0); + invalid_chunk[0] = (stbi__uint8) (c.type >> 24); + invalid_chunk[1] = (stbi__uint8) (c.type >> 16); + invalid_chunk[2] = (stbi__uint8) (c.type >> 8); + invalid_chunk[3] = (stbi__uint8) (c.type >> 0); #endif return e(invalid_chunk, "PNG not supported: unknown chunk type"); } @@ -2990,21 +2853,18 @@ static int parse_png_file(png *z, int scan, int req_comp) static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp) { unsigned char *result=NULL; - p->expanded = NULL; - p->idata = NULL; - p->out = NULL; if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); if (parse_png_file(p, SCAN_load, req_comp)) { result = p->out; p->out = NULL; - if (req_comp && req_comp != p->s.img_out_n) { - result = convert_format(result, p->s.img_out_n, req_comp, p->s.img_x, p->s.img_y); - p->s.img_out_n = req_comp; + if (req_comp && req_comp != p->s->img_out_n) { + result = convert_format(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; + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; } free(p->out); p->out = NULL; free(p->expanded); p->expanded = NULL; @@ -3013,89 +2873,37 @@ static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp) return result; } -#ifndef STBI_NO_STDIO -unsigned char *stbi_png_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +static unsigned char *stbi_png_load(stbi *s, int *x, int *y, int *comp, int req_comp) { png p; - start_file(&p.s, f); + p.s = s; return do_png(&p, x,y,comp,req_comp); } -unsigned char *stbi_png_load(char const *filename, int *x, int *y, int *comp, int req_comp) +static int stbi_png_test(stbi *s) { - unsigned char *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_png_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return data; -} -#endif - -unsigned char *stbi_png_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - png p; - start_mem(&p.s, buffer,len); - return do_png(&p, x,y,comp,req_comp); -} - -#ifndef STBI_NO_STDIO -int stbi_png_test_file(FILE *f) -{ - png p; - int n,r; - n = ftell(f); - start_file(&p.s, f); - r = parse_png_file(&p, SCAN_type,STBI_default); - fseek(f,n,SEEK_SET); + int r; + r = check_png_header(s); + stbi_rewind(s); return r; } -#endif - -int stbi_png_test_memory(stbi_uc const *buffer, int len) -{ - png p; - start_mem(&p.s, buffer, len); - return parse_png_file(&p, SCAN_type,STBI_default); -} static int stbi_png_info_raw(png *p, int *x, int *y, int *comp) { - if (!parse_png_file(p, SCAN_header, 0)) + if (!parse_png_file(p, 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; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; return 1; } -#ifndef STBI_NO_STDIO -int stbi_png_info (char const *filename, int *x, int *y, int *comp) -{ - int res; - FILE *f = fopen(filename, "rb"); - if (!f) return 0; - res = stbi_png_info_from_file(f, x, y, comp); - fclose(f); - return res; -} - -int stbi_png_info_from_file(FILE *f, int *x, int *y, int *comp) +static int stbi_png_info(stbi *s, int *x, int *y, int *comp) { png p; - int res; - long n = ftell(f); - start_file(&p.s, f); - res = stbi_png_info_raw(&p, x, y, comp); - fseek(f, n, SEEK_SET); - return res; -} -#endif // !STBI_NO_STDIO - -int stbi_png_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) -{ - png p; - start_mem(&p.s, buffer, len); + p.s = s; return stbi_png_info_raw(&p, x, y, comp); } @@ -3115,24 +2923,13 @@ static int bmp_test(stbi *s) return 0; } -#ifndef STBI_NO_STDIO -int stbi_bmp_test_file (FILE *f) +static int stbi_bmp_test(stbi *s) { - stbi s; - int r,n = ftell(f); - start_file(&s,f); - r = bmp_test(&s); - fseek(f,n,SEEK_SET); + int r = bmp_test(s); + stbi_rewind(s); return r; } -#endif -int stbi_bmp_test_memory (stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return bmp_test(&s); -} // returns 0..31 for the highest set bit static int high_bit(unsigned int z) @@ -3176,7 +2973,7 @@ static int shiftsigned(int v, int shift, int bits) static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) { - uint8 *out; + stbi__uint8 *out; unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; stbi_uc pal[256][4]; int psize=0,i,j,compress=0,width; @@ -3227,6 +3024,7 @@ static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) mb = 0xffu << 0; ma = 0xffu << 24; fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 + STBI_NOTUSED(fake_a); } else { mr = 31u << 10; mg = 31u << 5; @@ -3311,16 +3109,16 @@ static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) if (bpp == 24) { easy = 1; } else if (bpp == 32) { - if (mb == 0xff && mg == 0xff00 && mr == 0xff000000 && ma == 0xff000000) + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) easy = 2; } if (!easy) { - if (!mr || !mg || !mb) return epuc("bad masks", "Corrupt BMP"); + if (!mr || !mg || !mb) { free(out); return epuc("bad masks", "Corrupt BMP"); } // right shift amt to put high bit in position #7 rshift = high_bit(mr)-7; rcount = bitcount(mr); - gshift = high_bit(mg)-7; gcount = bitcount(mr); - bshift = high_bit(mb)-7; bcount = bitcount(mr); - ashift = high_bit(ma)-7; acount = bitcount(mr); + gshift = high_bit(mg)-7; gcount = bitcount(mg); + bshift = high_bit(mb)-7; bcount = bitcount(mb); + ashift = high_bit(ma)-7; acount = bitcount(ma); } for (j=0; j < (int) s->img_y; ++j) { if (easy) { @@ -3331,17 +3129,17 @@ static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) out[z+0] = get8u(s); z += 3; a = (easy == 2 ? get8(s) : 255); - if (target == 4) out[z++] = (uint8) a; + if (target == 4) out[z++] = (stbi__uint8) a; } } else { for (i=0; i < (int) s->img_x; ++i) { - uint32 v = (bpp == 16 ? get16le(s) : get32le(s)); + stbi__uint32 v = (stbi__uint32) (bpp == 16 ? get16le(s) : get32le(s)); int a; - out[z++] = (uint8) shiftsigned(v & mr, rshift, rcount); - out[z++] = (uint8) shiftsigned(v & mg, gshift, gcount); - out[z++] = (uint8) shiftsigned(v & mb, bshift, bcount); + out[z++] = (stbi__uint8) shiftsigned(v & mr, rshift, rcount); + out[z++] = (stbi__uint8) shiftsigned(v & mg, gshift, gcount); + out[z++] = (stbi__uint8) shiftsigned(v & mb, bshift, bcount); a = (ma ? shiftsigned(v & ma, ashift, acount) : 255); - if (target == 4) out[z++] = (uint8) a; + if (target == 4) out[z++] = (stbi__uint8) a; } } skip(s, pad); @@ -3365,35 +3163,15 @@ static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) *x = s->img_x; *y = s->img_y; - if (comp) *comp = target; + if (comp) *comp = s->img_n; return out; } -#ifndef STBI_NO_STDIO -stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp) +static stbi_uc *stbi_bmp_load(stbi *s,int *x, int *y, int *comp, int req_comp) { - stbi_uc *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_bmp_load_from_file(f, x,y,comp,req_comp); - fclose(f); - return data; + return bmp_load(s, x,y,comp,req_comp); } -stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s, f); - return bmp_load(&s, x,y,comp,req_comp); -} -#endif - -stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s, buffer, len); - return bmp_load(&s, x,y,comp,req_comp); -} // Targa Truevision - TGA // by Jonathan Dummer @@ -3404,22 +3182,30 @@ static int tga_info(stbi *s, int *x, int *y, int *comp) int sz; get8u(s); // discard Offset sz = get8u(s); // color type - if( sz > 1 ) return 0; // only RGB or indexed allowed + if( sz > 1 ) { + stbi_rewind(s); + return 0; // only RGB or indexed allowed + } sz = get8u(s); // image type // only RGB or grey allowed, +/- RLE if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; - get16le(s); // discard palette start - get16le(s); // discard palette length - get8(s); // discard bits per palette color entry - get16le(s); // discard x origin - get16le(s); // discard y origin + skip(s,9); tga_w = get16le(s); - if( tga_w < 1 ) return 0; // test width + if( tga_w < 1 ) { + stbi_rewind(s); + return 0; // test width + } tga_h = get16le(s); - if( tga_h < 1 ) return 0; // test height + if( tga_h < 1 ) { + stbi_rewind(s); + return 0; // test height + } sz = get8(s); // bits per pixel // only RGB or RGBA or grey allowed - if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) return 0; + if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) { + stbi_rewind(s); + return 0; + } tga_comp = sz; if (x) *x = tga_w; if (y) *y = tga_h; @@ -3427,11 +3213,9 @@ static int tga_info(stbi *s, int *x, int *y, int *comp) return 1; // seems to have passed everything } -int stbi_tga_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +int stbi_tga_info(stbi *s, int *x, int *y, int *comp) { - stbi s; - start_mem(&s, buffer, len); - return tga_info(&s, x, y, comp); + return tga_info(s, x, y, comp); } static int tga_test(stbi *s) @@ -3454,34 +3238,11 @@ static int tga_test(stbi *s) return 1; // seems to have passed everything } -#ifndef STBI_NO_STDIO -int stbi_tga_info_from_file(FILE *f, int *x, int *y, int *comp) +static int stbi_tga_test(stbi *s) { - stbi s; - int r; - long n = ftell(f); - start_file(&s, f); - r = tga_info(&s, x, y, comp); - fseek(f, n, SEEK_SET); - return r; -} - -int stbi_tga_test_file (FILE *f) -{ - stbi s; - int r,n = ftell(f); - start_file(&s, f); - r = tga_test(&s); - fseek(f,n,SEEK_SET); - return r; -} -#endif - -int stbi_tga_test_memory (stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return tga_test(&s); + int res = tga_test(s); + stbi_rewind(s); + return res; } static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) @@ -3499,13 +3260,13 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) int tga_width = get16le(s); int tga_height = get16le(s); int tga_bits_per_pixel = get8u(s); + int tga_comp = tga_bits_per_pixel / 8; int tga_inverted = get8u(s); // image data unsigned char *tga_data; unsigned char *tga_palette = NULL; int i, j; unsigned char raw_data[4]; - unsigned char trans_data[4]; int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; @@ -3527,176 +3288,149 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) ) { - return NULL; + return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA } // If I'm paletted, then I'll use the number of bits from the palette if ( tga_indexed ) { - tga_bits_per_pixel = tga_palette_bits; + tga_comp = tga_palette_bits / 8; } // tga info *x = tga_width; *y = tga_height; - if ( (req_comp < 1) || (req_comp > 4) ) - { - // just use whatever the file was - req_comp = tga_bits_per_pixel / 8; - *comp = req_comp; - } else - { - // force a new number of components - *comp = tga_bits_per_pixel/8; - } + if (comp) *comp = tga_comp; + tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp ); + if (!tga_data) return epuc("outofmem", "Out of memory"); // skip to the data's starting position (offset usually = 0) skip(s, tga_offset ); - // do I need to load a palette? - if ( tga_indexed ) - { - // any data to skip? (offset usually = 0) - skip(s, tga_palette_start ); - // load the palette - tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); - if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) - return NULL; - } - // load the data - trans_data[0] = trans_data[1] = trans_data[2] = trans_data[3] = 0; - for (i=0; i < tga_width * tga_height; ++i) - { - // if I'm in RLE mode, do I need to get a RLE chunk? - if ( tga_is_RLE ) - { - if ( RLE_count == 0 ) - { - // yep, get the next byte as a RLE command - int RLE_cmd = get8u(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; + + if ( !tga_indexed && !tga_is_RLE) { + for (i=0; i < tga_height; ++i) { + int y = tga_inverted ? tga_height -i - 1 : i; + stbi__uint8 *tga_row = tga_data + y*tga_width*tga_comp; + getn(s, tga_row, tga_width * tga_comp); } - // OK, if I need to read a pixel, do it now - if ( read_next_pixel ) + } else { + // do I need to load a palette? + if ( tga_indexed) { - // load however much data we did have - if ( tga_indexed ) + // any data to skip? (offset usually = 0) + skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); + if (!tga_palette) { + free(tga_data); + return epuc("outofmem", "Out of memory"); + } + if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { + free(tga_data); + free(tga_palette); + return epuc("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 chunk? + if ( tga_is_RLE ) { - // read in 1 byte, then perform the lookup - int pal_idx = get8u(s); - if ( pal_idx >= tga_palette_len ) + if ( RLE_count == 0 ) { - // invalid index - pal_idx = 0; - } - pal_idx *= tga_bits_per_pixel / 8; - for (j = 0; j*8 < tga_bits_per_pixel; ++j) + // yep, get the next byte as a RLE command + int RLE_cmd = get8u(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) { - raw_data[j] = tga_palette[pal_idx+j]; + read_next_pixel = 1; } } else { - // read in the data raw - for (j = 0; j*8 < tga_bits_per_pixel; ++j) + 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 ) { - raw_data[j] = get8u(s); + // read in 1 byte, then perform the lookup + int pal_idx = get8u(s); + if ( pal_idx >= tga_palette_len ) + { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_bits_per_pixel / 8; + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else + { + // read in the data raw + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = get8u(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 * req_comp; + int index2 = (tga_height - 1 - j) * tga_width * req_comp; + for (i = tga_width * req_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; } } - // convert raw to the intermediate format - switch (tga_bits_per_pixel) - { - case 8: - // Luminous => RGBA - trans_data[0] = raw_data[0]; - trans_data[1] = raw_data[0]; - trans_data[2] = raw_data[0]; - trans_data[3] = 255; - break; - case 16: - // Luminous,Alpha => RGBA - trans_data[0] = raw_data[0]; - trans_data[1] = raw_data[0]; - trans_data[2] = raw_data[0]; - trans_data[3] = raw_data[1]; - break; - case 24: - // BGR => RGBA - trans_data[0] = raw_data[2]; - trans_data[1] = raw_data[1]; - trans_data[2] = raw_data[0]; - trans_data[3] = 255; - break; - case 32: - // BGRA => RGBA - trans_data[0] = raw_data[2]; - trans_data[1] = raw_data[1]; - trans_data[2] = raw_data[0]; - trans_data[3] = raw_data[3]; - break; - } - // clear the reading flag for the next pixel - read_next_pixel = 0; - } // end of reading a pixel - // convert to final format - switch (req_comp) - { - case 1: - // RGBA => Luminance - tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); - break; - case 2: - // RGBA => Luminance,Alpha - tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); - tga_data[i*req_comp+1] = trans_data[3]; - break; - case 3: - // RGBA => RGB - tga_data[i*req_comp+0] = trans_data[0]; - tga_data[i*req_comp+1] = trans_data[1]; - tga_data[i*req_comp+2] = trans_data[2]; - break; - case 4: - // RGBA => RGBA - tga_data[i*req_comp+0] = trans_data[0]; - tga_data[i*req_comp+1] = trans_data[1]; - tga_data[i*req_comp+2] = trans_data[2]; - tga_data[i*req_comp+3] = trans_data[3]; - break; } - // 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) + // clear my palette, if I had one + if ( tga_palette != NULL ) { - int index1 = j * tga_width * req_comp; - int index2 = (tga_height - 1 - j) * tga_width * req_comp; - for (i = tga_width * req_comp; i > 0; --i) - { - unsigned char temp = tga_data[index1]; - tga_data[index1] = tga_data[index2]; - tga_data[index2] = temp; - ++index1; - ++index2; - } + free( tga_palette ); } } - // clear my palette, if I had one - if ( tga_palette != NULL ) + + // swap RGB + if (tga_comp >= 3) { - free( tga_palette ); + 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 = 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 = @@ -3705,30 +3439,9 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) return tga_data; } -#ifndef STBI_NO_STDIO -stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp) +static stbi_uc *stbi_tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) { - stbi_uc *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_tga_load_from_file(f, x,y,comp,req_comp); - fclose(f); - return data; -} - -stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s, f); - return tga_load(&s, x,y,comp,req_comp); -} -#endif - -stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s, buffer, len); - return tga_load(&s, x,y,comp,req_comp); + return tga_load(s,x,y,comp,req_comp); } @@ -3741,24 +3454,12 @@ static int psd_test(stbi *s) else return 1; } -#ifndef STBI_NO_STDIO -int stbi_psd_test_file(FILE *f) +static int stbi_psd_test(stbi *s) { - stbi s; - int r,n = ftell(f); - start_file(&s, f); - r = psd_test(&s); - fseek(f,n,SEEK_SET); + int r = psd_test(s); + stbi_rewind(s); return r; } -#endif - -int stbi_psd_test_memory(stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return psd_test(&s); -} static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) { @@ -3766,7 +3467,7 @@ static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) int channelCount, compression; int channel, i, count, len; int w,h; - uint8 *out; + stbi__uint8 *out; // Check identifier if (get32(s) != 0x38425053) // "8BPS" @@ -3787,7 +3488,7 @@ static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) // Read the rows and columns of the image. h = get32(s); w = get32(s); - + // Make sure the depth is 8 bits. if (get16(s) != 8) return epuc("unsupported bit depth", "PSD bit depth is not 8 bit"); @@ -3829,7 +3530,7 @@ static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) // Initialize the data to zero. //memset( out, 0, pixelCount * 4 ); - + // Finally, the image data. if (compression) { // RLE as used by .PSD and .TIFF @@ -3846,8 +3547,8 @@ static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) // Read the RLE data by channel. for (channel = 0; channel < 4; channel++) { - uint8 *p; - + stbi__uint8 *p; + p = out+channel; if (channel >= channelCount) { // Fill this channel with default data. @@ -3869,7 +3570,7 @@ static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) len--; } } else if (len > 128) { - uint8 val; + stbi__uint8 val; // Next -len+1 bytes in the dest are replicated from next source byte. // (Interpret len as a negative 8-bit int.) len ^= 0x0FF; @@ -3885,15 +3586,15 @@ static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) } } } - + } 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 value for each pixel in the image. - + // Read the data by channel. for (channel = 0; channel < 4; channel++) { - uint8 *p; - + stbi__uint8 *p; + p = out + channel; if (channel > channelCount) { // Fill this channel with default data. @@ -3914,34 +3615,13 @@ static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) if (comp) *comp = channelCount; *y = h; *x = w; - + return out; } -#ifndef STBI_NO_STDIO -stbi_uc *stbi_psd_load(char const *filename, int *x, int *y, int *comp, int req_comp) +static stbi_uc *stbi_psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) { - stbi_uc *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_psd_load_from_file(f, x,y,comp,req_comp); - fclose(f); - return data; -} - -stbi_uc *stbi_psd_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s, f); - return psd_load(&s, x,y,comp,req_comp); -} -#endif - -stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s, buffer, len); - return psd_load(&s, x,y,comp,req_comp); + return psd_load(s,x,y,comp,req_comp); } // ************************************************************************************************* @@ -4064,7 +3744,7 @@ static stbi_uc *pic_load2(stbi *s,int width,int height,int *comp, stbi_uc *resul if (at_eof(s)) return epuc("bad file","file too short (pure read count)"); if (count > left) - count = (uint8) left; + count = (stbi__uint8) left; if (!pic_readval(s,packet->channel,value)) return 0; @@ -4149,56 +3829,24 @@ static stbi_uc *pic_load(stbi *s,int *px,int *py,int *comp,int req_comp) return result; } -int stbi_pic_test_memory(stbi_uc const *buffer, int len) +static int stbi_pic_test(stbi *s) { - stbi s; - start_mem(&s,buffer,len); - return pic_test(&s); + int r = pic_test(s); + stbi_rewind(s); + return r; } -stbi_uc *stbi_pic_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +static stbi_uc *stbi_pic_load(stbi *s, int *x, int *y, int *comp, int req_comp) { - stbi s; - start_mem(&s,buffer,len); - return pic_load(&s,x,y,comp,req_comp); + return pic_load(s,x,y,comp,req_comp); } -#ifndef STBI_NO_STDIO -int stbi_pic_test_file(FILE *f) -{ - int result; - long l = ftell(f); - stbi s; - start_file(&s,f); - result = pic_test(&s); - fseek(f,l,SEEK_SET); - return result; -} - -stbi_uc *stbi_pic_load(char const *filename,int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *result; - FILE *f=fopen(filename,"rb"); - if (!f) return 0; - result = stbi_pic_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} - -stbi_uc *stbi_pic_load_from_file(FILE *f,int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s,f); - return pic_load(&s,x,y,comp,req_comp); -} -#endif - // ************************************************************************************************* // GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb typedef struct stbi_gif_lzw_struct { - int16 prefix; - uint8 first; - uint8 suffix; + stbi__int16 prefix; + stbi__uint8 first; + stbi__uint8 suffix; } stbi_gif_lzw; typedef struct stbi_gif_struct @@ -4206,10 +3854,10 @@ typedef struct stbi_gif_struct int w,h; stbi_uc *out; // output buffer (always 4 components) int flags, bgindex, ratio, transparent, eflags; - uint8 pal[256][4]; - uint8 lpal[256][4]; + stbi__uint8 pal[256][4]; + stbi__uint8 lpal[256][4]; stbi_gif_lzw codes[4096]; - uint8 *color_table; + stbi__uint8 *color_table; int parse, step; int lflags; int start_x, start_y; @@ -4228,26 +3876,14 @@ static int gif_test(stbi *s) return 1; } -#ifndef STBI_NO_STDIO -int stbi_gif_test_file (FILE *f) +static int stbi_gif_test(stbi *s) { - stbi s; - int r,n = ftell(f); - start_file(&s,f); - r = gif_test(&s); - fseek(f,n,SEEK_SET); + int r = gif_test(s); + stbi_rewind(s); return r; } -#endif -int stbi_gif_test_memory (stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return gif_test(&s); -} - -static void stbi_gif_parse_colortable(stbi *s, uint8 pal[256][4], int num_entries, int transp) +static void stbi_gif_parse_colortable(stbi *s, stbi__uint8 pal[256][4], int num_entries, int transp) { int i; for (i=0; i < num_entries; ++i) { @@ -4255,19 +3891,19 @@ static void stbi_gif_parse_colortable(stbi *s, uint8 pal[256][4], int num_entrie pal[i][1] = get8u(s); pal[i][0] = get8u(s); pal[i][3] = transp ? 0 : 255; - } + } } static int stbi_gif_header(stbi *s, stbi_gif *g, int *comp, int is_info) { - uint8 version; + stbi__uint8 version; if (get8(s) != 'G' || get8(s) != 'I' || get8(s) != 'F' || get8(s) != '8') return e("not GIF", "Corrupt GIF"); version = get8u(s); if (version != '7' && version != '9') return e("not GIF", "Corrupt GIF"); if (get8(s) != 'a') return e("not GIF", "Corrupt GIF"); - + failure_reason = ""; g->w = get16le(s); g->h = get16le(s); @@ -4288,16 +3924,19 @@ static int stbi_gif_header(stbi *s, stbi_gif *g, int *comp, int is_info) static int stbi_gif_info_raw(stbi *s, int *x, int *y, int *comp) { - stbi_gif g; - if (!stbi_gif_header(s, &g, comp, 1)) return 0; + stbi_gif g; + if (!stbi_gif_header(s, &g, comp, 1)) { + stbi_rewind( s ); + return 0; + } if (x) *x = g.w; if (y) *y = g.h; return 1; } -static void stbi_out_gif_code(stbi_gif *g, uint16 code) +static void stbi_out_gif_code(stbi_gif *g, stbi__uint16 code) { - uint8 *p, *c; + stbi__uint8 *p, *c; // recurse to decode the prefixes, since the linked-list is backwards, // and working backwards through an interleaved image would be nasty @@ -4305,7 +3944,7 @@ static void stbi_out_gif_code(stbi_gif *g, uint16 code) stbi_out_gif_code(g, g->codes[code].prefix); if (g->cur_y >= g->max_y) return; - + p = &g->out[g->cur_x + g->cur_y]; c = &g->color_table[g->codes[code].suffix * 4]; @@ -4329,12 +3968,12 @@ static void stbi_out_gif_code(stbi_gif *g, uint16 code) } } -static uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) +static stbi__uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) { - uint8 lzw_cs; - int32 len, code; - uint32 first; - int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__uint8 lzw_cs; + stbi__int32 len, code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; stbi_gif_lzw *p; lzw_cs = get8u(s); @@ -4346,8 +3985,8 @@ static uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) valid_bits = 0; for (code = 0; code < clear; code++) { g->codes[code].prefix = -1; - g->codes[code].first = (uint8) code; - g->codes[code].suffix = (uint8) code; + g->codes[code].first = (stbi__uint8) code; + g->codes[code].suffix = (stbi__uint8) code; } // support no starting clear code @@ -4359,14 +3998,14 @@ static uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) if (valid_bits < codesize) { if (len == 0) { len = get8(s); // start new block - if (len == 0) + if (len == 0) return g->out; } --len; - bits |= (int32) get8(s) << valid_bits; + bits |= (stbi__int32) get8(s) << valid_bits; valid_bits += 8; } else { - int32 code = bits & codemask; + stbi__int32 code = bits & codemask; bits >>= codesize; valid_bits -= codesize; // @OPTIMIZE: is there some way we can accelerate the non-clear path? @@ -4387,13 +4026,13 @@ static uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) if (oldcode >= 0) { p = &g->codes[avail++]; if (avail > 4096) return epuc("too many codes", "Corrupt GIF"); - p->prefix = (int16) oldcode; + 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 epuc("illegal code in raster", "Corrupt GIF"); - stbi_out_gif_code(g, (uint16) code); + stbi_out_gif_code(g, (stbi__uint16) code); if ((avail & codemask) == 0 && avail <= 0x0FFF) { codesize++; @@ -4404,17 +4043,17 @@ static uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) } else { return epuc("illegal code in raster", "Corrupt GIF"); } - } + } } } static void stbi_fill_gif_background(stbi_gif *g) { int i; - uint8 *c = g->pal[g->bgindex]; + stbi__uint8 *c = g->pal[g->bgindex]; // @OPTIMIZE: write a dword at a time for (i = 0; i < g->w * g->h * 4; i += 4) { - uint8 *p = &g->out[i]; + stbi__uint8 *p = &g->out[i]; p[0] = c[2]; p[1] = c[1]; p[2] = c[0]; @@ -4423,32 +4062,32 @@ static void stbi_fill_gif_background(stbi_gif *g) } // this function is designed to support animated gifs, although stb_image doesn't support it -static uint8 *stbi_gif_load_next(stbi *s, stbi_gif *g, int *comp, int req_comp) +static stbi__uint8 *stbi_gif_load_next(stbi *s, stbi_gif *g, int *comp, int req_comp) { int i; - uint8 *old_out = 0; + stbi__uint8 *old_out = 0; if (g->out == 0) { if (!stbi_gif_header(s, g, comp,0)) return 0; // failure_reason set by stbi_gif_header - g->out = (uint8 *) malloc(4 * g->w * g->h); + g->out = (stbi__uint8 *) malloc(4 * g->w * g->h); if (g->out == 0) return epuc("outofmem", "Out of memory"); stbi_fill_gif_background(g); } else { // animated-gif-only path if (((g->eflags & 0x1C) >> 2) == 3) { old_out = g->out; - g->out = (uint8 *) malloc(4 * g->w * g->h); + g->out = (stbi__uint8 *) malloc(4 * g->w * g->h); if (g->out == 0) return epuc("outofmem", "Out of memory"); memcpy(g->out, old_out, g->w*g->h*4); } } - + for (;;) { switch (get8(s)) { case 0x2C: /* Image Descriptor */ { - int32 x, y, w, h; - uint8 *o; + stbi__int32 x, y, w, h; + stbi__uint8 *o; x = get16le(s); y = get16le(s); @@ -4477,16 +4116,16 @@ static uint8 *stbi_gif_load_next(stbi *s, stbi_gif *g, int *comp, int req_comp) if (g->lflags & 0x80) { stbi_gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); - g->color_table = (uint8 *) g->lpal; + g->color_table = (stbi__uint8 *) g->lpal; } else if (g->flags & 0x80) { for (i=0; i < 256; ++i) // @OPTIMIZE: reset only the previous transparent - g->pal[i][3] = 255; + g->pal[i][3] = 255; if (g->transparent >= 0 && (g->eflags & 0x01)) g->pal[g->transparent][3] = 0; - g->color_table = (uint8 *) g->pal; + g->color_table = (stbi__uint8 *) g->pal; } else return epuc("missing color table", "Corrupt GIF"); - + o = stbi_process_gif_raster(s, g); if (o == NULL) return NULL; @@ -4515,7 +4154,7 @@ static uint8 *stbi_gif_load_next(stbi *s, stbi_gif *g, int *comp, int req_comp) } case 0x3B: // gif stream termination code - return (uint8 *) 1; + return (stbi__uint8 *) 1; default: return epuc("unknown code", "Corrupt GIF"); @@ -4523,25 +4162,12 @@ static uint8 *stbi_gif_load_next(stbi *s, stbi_gif *g, int *comp, int req_comp) } } -#ifndef STBI_NO_STDIO -stbi_uc *stbi_gif_load (char const *filename, int *x, int *y, int *comp, int req_comp) +static stbi_uc *stbi_gif_load(stbi *s, int *x, int *y, int *comp, int req_comp) { - uint8 *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_gif_load_from_file(f, x,y,comp,req_comp); - fclose(f); - return data; -} - -stbi_uc *stbi_gif_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) -{ - uint8 *u = 0; - stbi s; + stbi__uint8 *u = 0; stbi_gif g={0}; - start_file(&s, f); - u = stbi_gif_load_next(&s, &g, comp, req_comp); + u = stbi_gif_load_next(s, &g, comp, req_comp); if (u == (void *) 1) u = 0; // end of animated gif marker if (u) { *x = g.w; @@ -4550,55 +4176,12 @@ stbi_uc *stbi_gif_load_from_file (FILE *f, int *x, int *y, int *comp, int req_ return u; } -#endif -stbi_uc *stbi_gif_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +static int stbi_gif_info(stbi *s, int *x, int *y, int *comp) { - uint8 *u = 0; - stbi s; - stbi_gif g={0}; - start_mem(&s, buffer, len); - u = stbi_gif_load_next(&s, &g, comp, req_comp); - if (u == (void *) 1) u = 0; // end of animated gif marker - if (u) { - *x = g.w; - *y = g.h; - } - return u; + return stbi_gif_info_raw(s,x,y,comp); } -#ifndef STBI_NO_STDIO -int stbi_gif_info (char const *filename, int *x, int *y, int *comp) -{ - int res; - FILE *f = fopen(filename, "rb"); - if (!f) return 0; - res = stbi_gif_info_from_file(f, x, y, comp); - fclose(f); - return res; -} - -int stbi_gif_info_from_file(FILE *f, int *x, int *y, int *comp) -{ - stbi s; - int res; - long n = ftell(f); - start_file(&s, f); - res = stbi_gif_info_raw(&s, x, y, comp); - fseek(f, n, SEEK_SET); - return res; -} -#endif // !STBI_NO_STDIO - -int stbi_gif_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) -{ - stbi s; - start_mem(&s, buffer, len); - return stbi_gif_info_raw(&s, x, y, comp); -} - - - // ************************************************************************************************* // Radiance RGBE HDR loader @@ -4614,24 +4197,12 @@ static int hdr_test(stbi *s) return 1; } -int stbi_hdr_test_memory(stbi_uc const *buffer, int len) +static int stbi_hdr_test(stbi* s) { - stbi s; - start_mem(&s, buffer, len); - return hdr_test(&s); -} - -#ifndef STBI_NO_STDIO -int stbi_hdr_test_file(FILE *f) -{ - stbi s; - int r,n = ftell(f); - start_file(&s, f); - r = hdr_test(&s); - fseek(f,n,SEEK_SET); + int r = hdr_test(s); + stbi_rewind(s); return r; } -#endif #define HDR_BUFLEN 1024 static char *hdr_gettoken(stbi *z, char *buffer) @@ -4683,7 +4254,6 @@ static void hdr_convert(float *output, stbi_uc *input, int req_comp) } } - static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) { char buffer[HDR_BUFLEN]; @@ -4700,7 +4270,7 @@ static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) // Check identifier if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) return epf("not HDR", "Corrupt HDR image"); - + // Parse header for(;;) { token = hdr_gettoken(s,buffer); @@ -4715,11 +4285,11 @@ static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) token = hdr_gettoken(s,buffer); if (strncmp(token, "-Y ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); token += 3; - height = strtol(token, &token, 10); + height = (int) strtol(token, &token, 10); while (*token == ' ') ++token; if (strncmp(token, "+X ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); token += 3; - width = strtol(token, NULL, 10); + width = (int) strtol(token, NULL, 10); *x = width; *y = height; @@ -4753,11 +4323,11 @@ static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) 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) - uint8 rgbe[4]; - rgbe[0] = (uint8) c1; - rgbe[1] = (uint8) c2; - rgbe[2] = (uint8) len; - rgbe[3] = (uint8) get8u(s); + stbi__uint8 rgbe[4]; + rgbe[0] = (stbi__uint8) c1; + rgbe[1] = (stbi__uint8) c2; + rgbe[2] = (stbi__uint8) len; + rgbe[3] = (stbi__uint8) get8u(s); hdr_convert(hdr_data, rgbe, req_comp); i = 1; j = 0; @@ -4768,7 +4338,7 @@ static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) len |= get8(s); if (len != width) { free(hdr_data); free(scanline); return epf("invalid decoded scanline length", "corrupt HDR"); } if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4); - + for (k = 0; k < 4; ++k) { i = 0; while (i < width) { @@ -4795,24 +4365,178 @@ static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) return hdr_data; } -#ifndef STBI_NO_STDIO -float *stbi_hdr_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +static float *stbi_hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) { - stbi s; - start_file(&s,f); - return hdr_load(&s,x,y,comp,req_comp); -} -#endif - -float *stbi_hdr_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s,buffer, len); - return hdr_load(&s,x,y,comp,req_comp); + return hdr_load(s,x,y,comp,req_comp); } +static int stbi_hdr_info(stbi *s, int *x, int *y, int *comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) { + stbi_rewind( s ); + return 0; + } + + for(;;) { + token = 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 = 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 +static int stbi_bmp_info(stbi *s, int *x, int *y, int *comp) +{ + int hsz; + if (get8(s) != 'B' || get8(s) != 'M') { + stbi_rewind( s ); + return 0; + } + skip(s,12); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) { + stbi_rewind( s ); + return 0; + } + if (hsz == 12) { + *x = get16le(s); + *y = get16le(s); + } else { + *x = get32le(s); + *y = get32le(s); + } + if (get16le(s) != 1) { + stbi_rewind( s ); + return 0; + } + *comp = get16le(s) / 8; + return 1; +} + +static int stbi_psd_info(stbi *s, int *x, int *y, int *comp) +{ + int channelCount; + if (get32(s) != 0x38425053) { + stbi_rewind( s ); + return 0; + } + if (get16(s) != 1) { + stbi_rewind( s ); + return 0; + } + skip(s, 6); + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) { + stbi_rewind( s ); + return 0; + } + *y = get32(s); + *x = get32(s); + if (get16(s) != 8) { + stbi_rewind( s ); + return 0; + } + if (get16(s) != 3) { + stbi_rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi_pic_info(stbi *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained; + pic_packet_t packets[10]; + + skip(s, 92); + + *x = get16(s); + *y = get16(s); + if (at_eof(s)) return 0; + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi_rewind( s ); + return 0; + } + + skip(s, 8); + + do { + pic_packet_t *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = get8(s); + packet->size = get8u(s); + packet->type = get8u(s); + packet->channel = get8u(s); + act_comp |= packet->channel; + + if (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; +} + +static int stbi_info_main(stbi *s, int *x, int *y, int *comp) +{ + if (stbi_jpeg_info(s, x, y, comp)) + return 1; + if (stbi_png_info(s, x, y, comp)) + return 1; + if (stbi_gif_info(s, x, y, comp)) + return 1; + if (stbi_bmp_info(s, x, y, comp)) + return 1; + if (stbi_psd_info(s, x, y, comp)) + return 1; + if (stbi_pic_info(s, x, y, comp)) + return 1; + #ifndef STBI_NO_HDR + if (stbi_hdr_info(s, x, y, comp)) + return 1; + #endif + // test tga last because it's a crappy test! + if (stbi_tga_info(s, x, y, comp)) + return 1; + return e("unknown image type", "Image not of any known type, or corrupt"); +} #ifndef STBI_NO_STDIO int stbi_info(char const *filename, int *x, int *y, int *comp) @@ -4827,50 +4551,65 @@ int stbi_info(char const *filename, int *x, int *y, int *comp) int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) { - if (stbi_jpeg_info_from_file(f, x, y, comp)) - return 1; - if (stbi_png_info_from_file(f, x, y, comp)) - return 1; - if (stbi_gif_info_from_file(f, x, y, comp)) - return 1; - // @TODO: stbi_bmp_info_from_file - // @TODO: stbi_psd_info_from_file - #ifndef STBI_NO_HDR - // @TODO: stbi_hdr_info_from_file - #endif - // test tga last because it's a crappy test! - if (stbi_tga_info_from_file(f, x, y, comp)) - return 1; - return e("unknown image type", "Image not of any known type, or corrupt"); + int r; + stbi s; + long pos = ftell(f); + start_file(&s, f); + r = stbi_info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; } #endif // !STBI_NO_STDIO int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) { - if (stbi_jpeg_info_from_memory(buffer, len, x, y, comp)) - return 1; - if (stbi_png_info_from_memory(buffer, len, x, y, comp)) - return 1; - if (stbi_gif_info_from_memory(buffer, len, x, y, comp)) - return 1; - // @TODO: stbi_bmp_info_from_memory - // @TODO: stbi_psd_info_from_memory - #ifndef STBI_NO_HDR - // @TODO: stbi_hdr_info_from_memory - #endif - // test tga last because it's a crappy test! - if (stbi_tga_info_from_memory(buffer, len, x, y, comp)) - return 1; - return e("unknown image type", "Image not of any known type, or corrupt"); + stbi s; + start_mem(&s,buffer,len); + return stbi_info_main(&s,x,y,comp); +} + +int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi_info_main(&s,x,y,comp); } #endif // STBI_HEADER_FILE_ONLY +#if !defined(STBI_NO_STDIO) && defined(_MSC_VER) && _MSC_VER >= 1400 +#pragma warning(pop) +#endif + + /* revision history: - 1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ) + 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 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-uint8 to fix warnings + cast-to-stbi__uint8 to fix warnings 1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ 1.25 (2010-07-17) @@ -4882,13 +4621,12 @@ int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *c attempt to fix trans_data warning (Won Chun) 1.23 fixed bug in iPhone support 1.22 (2010-07-10) - removed image *writing* support 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.e. Janez (U+017D)emva) - 1.21 fix use of 'uint8' in header (reported by jon blow) + 1.21 fix use of 'stbi__uint8' 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 @@ -4928,8 +4666,7 @@ int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *c 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.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' @@ -4937,4 +4674,5 @@ int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *c 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 first released version */