|
|
|
@ -6,6 +6,8 @@ |
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION |
|
|
|
|
before you include this file in *one* C or C++ file to create the implementation. |
|
|
|
|
|
|
|
|
|
#define STBI_ASSERT(x) to avoid using assert.h. |
|
|
|
|
|
|
|
|
|
QUICK NOTES: |
|
|
|
|
Primarily of interest to game developers and other people who can |
|
|
|
|
avoid problematic images and only need the trivial interface |
|
|
|
@ -26,6 +28,7 @@ |
|
|
|
|
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) |
|
|
|
|
|
|
|
|
|
Latest revisions: |
|
|
|
|
1.42 (2014-07-09) no _CRT_SECURE_NO_WARNINGS; error-path fixes; STBI_ASSERT |
|
|
|
|
1.41 (2014-06-25) fix search&replace that messed up comments/error messages |
|
|
|
|
1.40 (2014-06-22) gcc warning |
|
|
|
|
1.39 (2014-06-15) TGA optimization fix, multiple BMP fixes |
|
|
|
@ -33,8 +36,6 @@ |
|
|
|
|
1.37 (2014-06-04) remove duplicate typedef |
|
|
|
|
1.36 (2014-06-03) converted to header file, allow reading incorrect iphoned-images without iphone flag |
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
See end of file for full revision history. |
|
|
|
|
|
|
|
|
@ -189,12 +190,6 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef STBI_NO_STDIO |
|
|
|
|
|
|
|
|
|
#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 <stdio.h> |
|
|
|
|
#endif // STBI_NO_STDIO
|
|
|
|
|
|
|
|
|
@ -354,8 +349,11 @@ STBIDEF void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); |
|
|
|
|
#include <stdio.h> |
|
|
|
|
#endif |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <memory.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#ifndef STBI_ASSERT |
|
|
|
|
#include <assert.h> |
|
|
|
|
#define STBI_ASSERT(x) assert(x) |
|
|
|
|
#endif |
|
|
|
|
#include <stdarg.h> |
|
|
|
|
#include <stddef.h> // ptrdiff_t on osx |
|
|
|
|
|
|
|
|
@ -574,9 +572,23 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef STBI_NO_STDIO |
|
|
|
|
|
|
|
|
|
FILE *stbi__fopen(char const *filename, char const *mode) |
|
|
|
|
{ |
|
|
|
|
FILE *f; |
|
|
|
|
#if _MSC_VER >= 1400 |
|
|
|
|
if (0 != fopen_s(&f, filename, "rb")) |
|
|
|
|
f=0; |
|
|
|
|
#else |
|
|
|
|
f = fopen(filename, "rb"); |
|
|
|
|
#endif |
|
|
|
|
return f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
STBIDEF unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) |
|
|
|
|
{ |
|
|
|
|
FILE *f = fopen(filename, "rb"); |
|
|
|
|
FILE *f = stbi__fopen(filename, "rb"); |
|
|
|
|
unsigned char *result; |
|
|
|
|
if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); |
|
|
|
|
result = stbi_load_from_file(f,x,y,comp,req_comp); |
|
|
|
@ -644,8 +656,8 @@ float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int |
|
|
|
|
#ifndef STBI_NO_STDIO |
|
|
|
|
float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) |
|
|
|
|
{ |
|
|
|
|
FILE *f = fopen(filename, "rb"); |
|
|
|
|
float *result; |
|
|
|
|
FILE *f = stbi__fopen(filename, "rb"); |
|
|
|
|
if (!f) return stbi__errpf("can't fopen", "Unable to open file"); |
|
|
|
|
result = stbi_loadf_from_file(f,x,y,comp,req_comp); |
|
|
|
|
fclose(f); |
|
|
|
@ -682,7 +694,7 @@ int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) |
|
|
|
|
#ifndef STBI_NO_STDIO |
|
|
|
|
STBIDEF int stbi_is_hdr (char const *filename) |
|
|
|
|
{ |
|
|
|
|
FILE *f = fopen(filename, "rb"); |
|
|
|
|
FILE *f = stbi__fopen(filename, "rb"); |
|
|
|
|
int result=0; |
|
|
|
|
if (f) { |
|
|
|
|
result = stbi_is_hdr_from_file(f); |
|
|
|
@ -860,7 +872,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r |
|
|
|
|
unsigned char *good; |
|
|
|
|
|
|
|
|
|
if (req_comp == img_n) return data; |
|
|
|
|
assert(req_comp >= 1 && req_comp <= 4); |
|
|
|
|
STBI_ASSERT(req_comp >= 1 && req_comp <= 4); |
|
|
|
|
|
|
|
|
|
good = (unsigned char *) malloc(req_comp * x * y); |
|
|
|
|
if (good == NULL) { |
|
|
|
@ -889,7 +901,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r |
|
|
|
|
CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; |
|
|
|
|
CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; |
|
|
|
|
CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; |
|
|
|
|
default: assert(0); |
|
|
|
|
default: STBI_ASSERT(0); |
|
|
|
|
} |
|
|
|
|
#undef CASE |
|
|
|
|
} |
|
|
|
@ -1126,7 +1138,7 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) |
|
|
|
|
|
|
|
|
|
// convert the huffman code to the symbol id
|
|
|
|
|
c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; |
|
|
|
|
assert((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); |
|
|
|
|
STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); |
|
|
|
|
|
|
|
|
|
// convert the id to a symbol
|
|
|
|
|
j->code_bits -= k; |
|
|
|
@ -1807,8 +1819,9 @@ static void stbi__cleanup_jpeg(stbi__jpeg *j) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
for (i=0; i < j->s->img_n; ++i) { |
|
|
|
|
if (j->img_comp[i].data) { |
|
|
|
|
if (j->img_comp[i].raw_data) { |
|
|
|
|
free(j->img_comp[i].raw_data); |
|
|
|
|
j->img_comp[i].raw_data = NULL; |
|
|
|
|
j->img_comp[i].data = NULL; |
|
|
|
|
} |
|
|
|
|
if (j->img_comp[i].linebuf) { |
|
|
|
@ -1831,9 +1844,10 @@ typedef struct |
|
|
|
|
static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) |
|
|
|
|
{ |
|
|
|
|
int n, decode_n; |
|
|
|
|
z->s->img_n = 0; // make stbi__cleanup_jpeg safe
|
|
|
|
|
|
|
|
|
|
// validate req_comp
|
|
|
|
|
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); |
|
|
|
|
z->s->img_n = 0; |
|
|
|
|
|
|
|
|
|
// load a jpeg image from whichever source
|
|
|
|
|
if (!decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } |
|
|
|
@ -1998,7 +2012,7 @@ stbi_inline static int stbi__bitreverse16(int n) |
|
|
|
|
|
|
|
|
|
stbi_inline static int stbi__bit_reverse(int v, int bits) |
|
|
|
|
{ |
|
|
|
|
assert(bits <= 16); |
|
|
|
|
STBI_ASSERT(bits <= 16); |
|
|
|
|
// to bit reverse n bits, reverse 16 and shift
|
|
|
|
|
// stbi__err.g. 11 bits, bit reverse and shift away 5
|
|
|
|
|
return stbi__bitreverse16(v) >> (16-bits); |
|
|
|
@ -2016,7 +2030,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) |
|
|
|
|
++sizes[sizelist[i]]; |
|
|
|
|
sizes[0] = 0; |
|
|
|
|
for (i=1; i < 16; ++i) |
|
|
|
|
assert(sizes[i] <= (1 << i)); |
|
|
|
|
STBI_ASSERT(sizes[i] <= (1 << i)); |
|
|
|
|
code = 0; |
|
|
|
|
for (i=1; i < 16; ++i) { |
|
|
|
|
next_code[i] = code; |
|
|
|
@ -2078,7 +2092,7 @@ stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) |
|
|
|
|
static void stbi__fill_bits(stbi__zbuf *z) |
|
|
|
|
{ |
|
|
|
|
do { |
|
|
|
|
assert(z->code_buffer < (1U << z->num_bits)); |
|
|
|
|
STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); |
|
|
|
|
z->code_buffer |= stbi__zget8(z) << z->num_bits; |
|
|
|
|
z->num_bits += 8; |
|
|
|
|
} while (z->num_bits <= 24); |
|
|
|
@ -2115,7 +2129,7 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) |
|
|
|
|
if (s == 16) return -1; // invalid code!
|
|
|
|
|
// code size is s, so:
|
|
|
|
|
b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; |
|
|
|
|
assert(z->size[b] == s); |
|
|
|
|
STBI_ASSERT(z->size[b] == s); |
|
|
|
|
a->code_buffer >>= s; |
|
|
|
|
a->num_bits -= s; |
|
|
|
|
return z->value[b]; |
|
|
|
@ -2202,7 +2216,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) |
|
|
|
|
n = 0; |
|
|
|
|
while (n < hlit + hdist) { |
|
|
|
|
int c = stbi__zhuffman_decode(a, &z_codelength); |
|
|
|
|
assert(c >= 0 && c < 19); |
|
|
|
|
STBI_ASSERT(c >= 0 && c < 19); |
|
|
|
|
if (c < 16) |
|
|
|
|
lencodes[n++] = (stbi_uc) c; |
|
|
|
|
else if (c == 16) { |
|
|
|
@ -2214,7 +2228,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) |
|
|
|
|
memset(lencodes+n, 0, c); |
|
|
|
|
n += c; |
|
|
|
|
} else { |
|
|
|
|
assert(c == 18); |
|
|
|
|
STBI_ASSERT(c == 18); |
|
|
|
|
c = stbi__zreceive(a,7)+11; |
|
|
|
|
memset(lencodes+n, 0, c); |
|
|
|
|
n += c; |
|
|
|
@ -2239,7 +2253,7 @@ static int stbi__parse_uncomperssed_block(stbi__zbuf *a) |
|
|
|
|
a->code_buffer >>= 8; |
|
|
|
|
a->num_bits -= 8; |
|
|
|
|
} |
|
|
|
|
assert(a->num_bits == 0); |
|
|
|
|
STBI_ASSERT(a->num_bits == 0); |
|
|
|
|
// now fill header the normal way
|
|
|
|
|
while (k < 4) |
|
|
|
|
header[k++] = stbi__zget8(a); |
|
|
|
@ -2468,7 +2482,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r |
|
|
|
|
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); |
|
|
|
|
STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); |
|
|
|
|
a->out = (stbi_uc *) malloc(x * y * out_n); |
|
|
|
|
if (!a->out) return stbi__err("outofmem", "Out of memory"); |
|
|
|
|
if (s->img_x == x && s->img_y == y) { |
|
|
|
@ -2516,7 +2530,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r |
|
|
|
|
} |
|
|
|
|
#undef CASE |
|
|
|
|
} else { |
|
|
|
|
assert(img_n+1 == out_n); |
|
|
|
|
STBI_ASSERT(img_n+1 == out_n); |
|
|
|
|
#define CASE(f) \ |
|
|
|
|
case f: \
|
|
|
|
|
for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \
|
|
|
|
@ -2581,7 +2595,7 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) |
|
|
|
|
|
|
|
|
|
// compute color-based transparency, assuming we've
|
|
|
|
|
// already got 255 as the alpha value in the output
|
|
|
|
|
assert(out_n == 2 || out_n == 4); |
|
|
|
|
STBI_ASSERT(out_n == 2 || out_n == 4); |
|
|
|
|
|
|
|
|
|
if (out_n == 2) { |
|
|
|
|
for (i=0; i < pixel_count; ++i) { |
|
|
|
@ -2662,7 +2676,7 @@ static void stbi__de_iphone(stbi__png *z) |
|
|
|
|
p += 3; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
assert(s->img_out_n == 4); |
|
|
|
|
STBI_ASSERT(s->img_out_n == 4); |
|
|
|
|
if (stbi__unpremultiply_on_load) { |
|
|
|
|
// convert bgr to rgb and unpremultiply
|
|
|
|
|
for (i=0; i < pixel_count; ++i) { |
|
|
|
@ -3036,7 +3050,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
|
return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
assert(hsz == 108 || hsz == 124); |
|
|
|
|
STBI_ASSERT(hsz == 108 || hsz == 124); |
|
|
|
|
mr = stbi__get32le(s); |
|
|
|
|
mg = stbi__get32le(s); |
|
|
|
|
mb = stbi__get32le(s); |
|
|
|
@ -4119,7 +4133,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case 0x3B: // gif stream termination code
|
|
|
|
|
return (stbi_uc *) 1; |
|
|
|
|
return (stbi_uc *) s; // using '1' causes warning on some compilers
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return stbi__errpuc("unknown code", "Corrupt GIF"); |
|
|
|
@ -4134,7 +4148,7 @@ static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
|
memset(&g, 0, sizeof(g)); |
|
|
|
|
|
|
|
|
|
u = stbi__gif_load_next(s, &g, comp, req_comp); |
|
|
|
|
if (u == (void *) 1) u = 0; // end of animated gif marker
|
|
|
|
|
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
|
|
|
|
|
if (u) { |
|
|
|
|
*x = g.w; |
|
|
|
|
*y = g.h; |
|
|
|
@ -4502,7 +4516,7 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) |
|
|
|
|
#ifndef STBI_NO_STDIO |
|
|
|
|
STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) |
|
|
|
|
{ |
|
|
|
|
FILE *f = fopen(filename, "rb"); |
|
|
|
|
FILE *f = stbi__fopen(filename, "rb"); |
|
|
|
|
int result; |
|
|
|
|
if (!f) return stbi__err("can't fopen", "Unable to open file"); |
|
|
|
|
result = stbi_info_from_file(f, x, y, comp); |
|
|
|
@ -4545,6 +4559,10 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
revision history: |
|
|
|
|
1.42 (2014-07-09) |
|
|
|
|
don't define _CRT_SECURE_NO_WARNINGS (affects user code) |
|
|
|
|
fixes to stbi__cleanup_jpeg path |
|
|
|
|
added STBI_ASSERT to avoid requiring assert.h |
|
|
|
|
1.41 (2014-06-25) |
|
|
|
|
fix search&replace from 1.36 that messed up comments/error messages |
|
|
|
|
1.40 (2014-06-22) |
|
|
|
|