|
@@ -1,4 +1,4 @@
|
|
-/* stb_image - v2.09 - public domain image loader - http://nothings.org/stb_image.h
|
|
|
|
|
|
+/* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h
|
|
no warranty implied; use at your own risk
|
|
no warranty implied; use at your own risk
|
|
|
|
|
|
Do this:
|
|
Do this:
|
|
@@ -146,6 +146,12 @@
|
|
|
|
|
|
|
|
|
|
Latest revision history:
|
|
Latest revision history:
|
|
|
|
+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
|
|
|
|
+ 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
|
|
|
|
+ RGB-format JPEG; remove white matting in PSD;
|
|
|
|
+ allocate large structures on the stack;
|
|
|
|
+ correct channel count for PNG & BMP
|
|
|
|
+ 2.10 (2016-01-22) avoid warning introduced in 2.09
|
|
2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
|
|
2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
|
|
2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
|
|
2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
|
|
2.07 (2015-09-13) partial animated GIF support
|
|
2.07 (2015-09-13) partial animated GIF support
|
|
@@ -166,10 +172,6 @@
|
|
STBI_MALLOC,STBI_REALLOC,STBI_FREE
|
|
STBI_MALLOC,STBI_REALLOC,STBI_FREE
|
|
STBI_NO_*, STBI_ONLY_*
|
|
STBI_NO_*, STBI_ONLY_*
|
|
GIF bugfix
|
|
GIF bugfix
|
|
- 1.48 (2014-12-14) fix incorrectly-named assert()
|
|
|
|
- 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted)
|
|
|
|
- optimize PNG
|
|
|
|
- fix bug in interlaced PNG with user-specified channel count
|
|
|
|
|
|
|
|
See end of file for full revision history.
|
|
See end of file for full revision history.
|
|
|
|
|
|
@@ -200,17 +202,17 @@
|
|
Janez Zemva John Bartholomew Michal Cichon svdijk@github
|
|
Janez Zemva John Bartholomew Michal Cichon svdijk@github
|
|
Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson
|
|
Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson
|
|
Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github
|
|
Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github
|
|
- Aruelien Pocheville Thibault Reuille Cass Everitt
|
|
|
|
- Ryamond Barbiero Paul Du Bois Engin Manap
|
|
|
|
|
|
+ Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan
|
|
|
|
+ Ryamond Barbiero Paul Du Bois Engin Manap snagar@github
|
|
|
|
+ Michaelangel007@github Oriol Ferrer Mesia socks-the-fox
|
|
Blazej Dariusz Roszkowski
|
|
Blazej Dariusz Roszkowski
|
|
- Michaelangel007@github
|
|
|
|
|
|
|
|
|
|
|
|
LICENSE
|
|
LICENSE
|
|
|
|
|
|
-This software is in the public domain. Where that dedication is not
|
|
|
|
-recognized, you are granted a perpetual, irrevocable license to copy,
|
|
|
|
-distribute, and modify this file as you see fit.
|
|
|
|
|
|
+This software is dual-licensed to the public domain and under the following
|
|
|
|
+license: you are granted a perpetual, irrevocable license to copy, modify,
|
|
|
|
+publish, and distribute this file as you see fit.
|
|
|
|
|
|
*/
|
|
*/
|
|
|
|
|
|
@@ -679,7 +681,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
|
|
#define STBI_NO_SIMD
|
|
#define STBI_NO_SIMD
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET)
|
|
|
|
|
|
+#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
|
|
#define STBI_SSE2
|
|
#define STBI_SSE2
|
|
#include <emmintrin.h>
|
|
#include <emmintrin.h>
|
|
|
|
|
|
@@ -1513,6 +1515,7 @@ typedef struct
|
|
int succ_high;
|
|
int succ_high;
|
|
int succ_low;
|
|
int succ_low;
|
|
int eob_run;
|
|
int eob_run;
|
|
|
|
+ int rgb;
|
|
|
|
|
|
int scan_n, order[4];
|
|
int scan_n, order[4];
|
|
int restart_interval, todo;
|
|
int restart_interval, todo;
|
|
@@ -2724,11 +2727,17 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
|
|
|
|
|
if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
|
|
if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
|
|
|
|
|
|
|
|
+ z->rgb = 0;
|
|
for (i=0; i < s->img_n; ++i) {
|
|
for (i=0; i < s->img_n; ++i) {
|
|
|
|
+ static unsigned char rgb[3] = { 'R', 'G', 'B' };
|
|
z->img_comp[i].id = stbi__get8(s);
|
|
z->img_comp[i].id = stbi__get8(s);
|
|
if (z->img_comp[i].id != i+1) // JFIF requires
|
|
if (z->img_comp[i].id != i+1) // JFIF requires
|
|
- if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files!
|
|
|
|
- return stbi__err("bad component ID","Corrupt JPEG");
|
|
|
|
|
|
+ if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files!
|
|
|
|
+ // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format)
|
|
|
|
+ if (z->img_comp[i].id != rgb[i])
|
|
|
|
+ return stbi__err("bad component ID","Corrupt JPEG");
|
|
|
|
+ ++z->rgb;
|
|
|
|
+ }
|
|
q = stbi__get8(s);
|
|
q = stbi__get8(s);
|
|
z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
|
|
z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
|
|
z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
|
|
z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
|
|
@@ -3390,7 +3399,17 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|
if (n >= 3) {
|
|
if (n >= 3) {
|
|
stbi_uc *y = coutput[0];
|
|
stbi_uc *y = coutput[0];
|
|
if (z->s->img_n == 3) {
|
|
if (z->s->img_n == 3) {
|
|
- z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
|
|
|
|
|
|
+ if (z->rgb == 3) {
|
|
|
|
+ for (i=0; i < z->s->img_x; ++i) {
|
|
|
|
+ out[0] = y[i];
|
|
|
|
+ out[1] = coutput[1][i];
|
|
|
|
+ out[2] = coutput[2][i];
|
|
|
|
+ out[3] = 255;
|
|
|
|
+ out += n;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
|
|
|
|
+ }
|
|
} else
|
|
} 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[0] = out[1] = out[2] = y[i];
|
|
@@ -3415,10 +3434,13 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|
|
|
|
|
static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
|
static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
|
{
|
|
{
|
|
- stbi__jpeg j;
|
|
|
|
- j.s = s;
|
|
|
|
- stbi__setup_jpeg(&j);
|
|
|
|
- return load_jpeg_image(&j, x,y,comp,req_comp);
|
|
|
|
|
|
+ unsigned char* result;
|
|
|
|
+ stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
|
|
|
|
+ j->s = s;
|
|
|
|
+ stbi__setup_jpeg(j);
|
|
|
|
+ result = load_jpeg_image(j, x,y,comp,req_comp);
|
|
|
|
+ STBI_FREE(j);
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
|
|
|
|
static int stbi__jpeg_test(stbi__context *s)
|
|
static int stbi__jpeg_test(stbi__context *s)
|
|
@@ -3446,9 +3468,12 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
|
|
|
|
|
|
static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
|
|
static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
|
|
{
|
|
{
|
|
- stbi__jpeg j;
|
|
|
|
- j.s = s;
|
|
|
|
- return stbi__jpeg_info_raw(&j, x, y, comp);
|
|
|
|
|
|
+ int result;
|
|
|
|
+ stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
|
|
|
|
+ j->s = s;
|
|
|
|
+ result = stbi__jpeg_info_raw(j, x, y, comp);
|
|
|
|
+ STBI_FREE(j);
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -3629,6 +3654,7 @@ static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room
|
|
while (cur + n > limit)
|
|
while (cur + n > limit)
|
|
limit *= 2;
|
|
limit *= 2;
|
|
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
|
|
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
|
|
|
|
+ STBI_NOTUSED(old_limit);
|
|
if (q == NULL) return stbi__err("outofmem", "Out of memory");
|
|
if (q == NULL) return stbi__err("outofmem", "Out of memory");
|
|
z->zout_start = q;
|
|
z->zout_start = q;
|
|
z->zout = q + cur;
|
|
z->zout = q + cur;
|
|
@@ -3738,7 +3764,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
-static int stbi__parse_uncomperssed_block(stbi__zbuf *a)
|
|
|
|
|
|
+static int stbi__parse_uncompressed_block(stbi__zbuf *a)
|
|
{
|
|
{
|
|
stbi_uc header[4];
|
|
stbi_uc header[4];
|
|
int len,nlen,k;
|
|
int len,nlen,k;
|
|
@@ -3804,7 +3830,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
|
|
final = stbi__zreceive(a,1);
|
|
final = stbi__zreceive(a,1);
|
|
type = stbi__zreceive(a,2);
|
|
type = stbi__zreceive(a,2);
|
|
if (type == 0) {
|
|
if (type == 0) {
|
|
- if (!stbi__parse_uncomperssed_block(a)) return 0;
|
|
|
|
|
|
+ if (!stbi__parse_uncompressed_block(a)) return 0;
|
|
} else if (type == 3) {
|
|
} else if (type == 3) {
|
|
return 0;
|
|
return 0;
|
|
} else {
|
|
} else {
|
|
@@ -3946,6 +3972,7 @@ typedef struct
|
|
{
|
|
{
|
|
stbi__context *s;
|
|
stbi__context *s;
|
|
stbi_uc *idata, *expanded, *out;
|
|
stbi_uc *idata, *expanded, *out;
|
|
|
|
+ int depth;
|
|
} stbi__png;
|
|
} stbi__png;
|
|
|
|
|
|
|
|
|
|
@@ -3985,14 +4012,19 @@ static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x0
|
|
// create the png data from post-deflated data
|
|
// create the png data from post-deflated data
|
|
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
|
|
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
|
|
{
|
|
{
|
|
|
|
+ int bytes = (depth == 16? 2 : 1);
|
|
stbi__context *s = a->s;
|
|
stbi__context *s = a->s;
|
|
- stbi__uint32 i,j,stride = x*out_n;
|
|
|
|
|
|
+ stbi__uint32 i,j,stride = x*out_n*bytes;
|
|
stbi__uint32 img_len, img_width_bytes;
|
|
stbi__uint32 img_len, img_width_bytes;
|
|
int k;
|
|
int k;
|
|
int img_n = s->img_n; // copy it into a local for later
|
|
int img_n = s->img_n; // copy it into a local for later
|
|
|
|
|
|
|
|
+ int output_bytes = out_n*bytes;
|
|
|
|
+ int filter_bytes = img_n*bytes;
|
|
|
|
+ int width = x;
|
|
|
|
+
|
|
STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
|
|
STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
|
|
- a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into
|
|
|
|
|
|
+ a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into
|
|
if (!a->out) return stbi__err("outofmem", "Out of memory");
|
|
if (!a->out) return stbi__err("outofmem", "Out of memory");
|
|
|
|
|
|
img_width_bytes = (((img_n * x * depth) + 7) >> 3);
|
|
img_width_bytes = (((img_n * x * depth) + 7) >> 3);
|
|
@@ -4007,8 +4039,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
stbi_uc *cur = a->out + stride*j;
|
|
stbi_uc *cur = a->out + stride*j;
|
|
stbi_uc *prior = cur - stride;
|
|
stbi_uc *prior = cur - stride;
|
|
int filter = *raw++;
|
|
int filter = *raw++;
|
|
- int filter_bytes = img_n;
|
|
|
|
- int width = x;
|
|
|
|
|
|
+
|
|
if (filter > 4)
|
|
if (filter > 4)
|
|
return stbi__err("invalid filter","Corrupt PNG");
|
|
return stbi__err("invalid filter","Corrupt PNG");
|
|
|
|
|
|
@@ -4041,6 +4072,14 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
raw += img_n;
|
|
raw += img_n;
|
|
cur += out_n;
|
|
cur += out_n;
|
|
prior += out_n;
|
|
prior += out_n;
|
|
|
|
+ } else if (depth == 16) {
|
|
|
|
+ if (img_n != out_n) {
|
|
|
|
+ cur[filter_bytes] = 255; // first pixel top byte
|
|
|
|
+ cur[filter_bytes+1] = 255; // first pixel bottom byte
|
|
|
|
+ }
|
|
|
|
+ raw += filter_bytes;
|
|
|
|
+ cur += output_bytes;
|
|
|
|
+ prior += output_bytes;
|
|
} else {
|
|
} else {
|
|
raw += 1;
|
|
raw += 1;
|
|
cur += 1;
|
|
cur += 1;
|
|
@@ -4049,7 +4088,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
|
|
|
|
// this is a little gross, so that we don't switch per-pixel or per-component
|
|
// this is a little gross, so that we don't switch per-pixel or per-component
|
|
if (depth < 8 || img_n == out_n) {
|
|
if (depth < 8 || img_n == out_n) {
|
|
- int nk = (width - 1)*img_n;
|
|
|
|
|
|
+ int nk = (width - 1)*filter_bytes;
|
|
#define CASE(f) \
|
|
#define CASE(f) \
|
|
case f: \
|
|
case f: \
|
|
for (k=0; k < nk; ++k)
|
|
for (k=0; k < nk; ++k)
|
|
@@ -4069,18 +4108,27 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
STBI_ASSERT(img_n+1 == out_n);
|
|
STBI_ASSERT(img_n+1 == out_n);
|
|
#define CASE(f) \
|
|
#define CASE(f) \
|
|
case f: \
|
|
case f: \
|
|
- for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \
|
|
|
|
- for (k=0; k < img_n; ++k)
|
|
|
|
|
|
+ for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
|
|
|
|
+ for (k=0; k < filter_bytes; ++k)
|
|
switch (filter) {
|
|
switch (filter) {
|
|
CASE(STBI__F_none) cur[k] = raw[k]; break;
|
|
CASE(STBI__F_none) cur[k] = raw[k]; break;
|
|
- CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break;
|
|
|
|
|
|
+ CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break;
|
|
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
|
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
|
- CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break;
|
|
|
|
- CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break;
|
|
|
|
- CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break;
|
|
|
|
- CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break;
|
|
|
|
|
|
+ CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break;
|
|
|
|
+ CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break;
|
|
|
|
+ CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break;
|
|
|
|
+ CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break;
|
|
}
|
|
}
|
|
#undef CASE
|
|
#undef CASE
|
|
|
|
+
|
|
|
|
+ // the loop above sets the high byte of the pixels' alpha, but for
|
|
|
|
+ // 16 bit png files we also need the low byte set. we'll do that here.
|
|
|
|
+ if (depth == 16) {
|
|
|
|
+ cur = a->out + stride*j; // start at the beginning of the row again
|
|
|
|
+ for (i=0; i < x; ++i,cur+=output_bytes) {
|
|
|
|
+ cur[filter_bytes+1] = 255;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4156,6 +4204,17 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ } else if (depth == 16) {
|
|
|
|
+ // force the image data from big-endian to platform-native.
|
|
|
|
+ // this is done in a separate pass due to the decoding relying
|
|
|
|
+ // on the data being untouched, but could probably be done
|
|
|
|
+ // per-line during decode if care is taken.
|
|
|
|
+ stbi_uc *cur = a->out;
|
|
|
|
+ stbi__uint16 *cur16 = (stbi__uint16*)cur;
|
|
|
|
+
|
|
|
|
+ for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
|
|
|
|
+ *cur16 = (cur[0] << 8) | cur[1];
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
@@ -4228,6 +4287,31 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
|
|
|
|
+{
|
|
|
|
+ stbi__context *s = z->s;
|
|
|
|
+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;
|
|
|
|
+ stbi__uint16 *p = (stbi__uint16*) z->out;
|
|
|
|
+
|
|
|
|
+ // compute color-based transparency, assuming we've
|
|
|
|
+ // already got 65535 as the alpha value in the output
|
|
|
|
+ STBI_ASSERT(out_n == 2 || out_n == 4);
|
|
|
|
+
|
|
|
|
+ if (out_n == 2) {
|
|
|
|
+ for (i = 0; i < pixel_count; ++i) {
|
|
|
|
+ p[1] = (p[0] == tc[0] ? 0 : 65535);
|
|
|
|
+ p += 2;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ for (i = 0; i < pixel_count; ++i) {
|
|
|
|
+ if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
|
|
|
|
+ p[3] = 0;
|
|
|
|
+ p += 4;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
|
|
static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
|
|
{
|
|
{
|
|
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
|
|
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
|
|
@@ -4265,6 +4349,26 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int stbi__reduce_png(stbi__png *p)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+ int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n;
|
|
|
|
+ stbi_uc *reduced;
|
|
|
|
+ stbi__uint16 *orig = (stbi__uint16*)p->out;
|
|
|
|
+
|
|
|
|
+ if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data
|
|
|
|
+
|
|
|
|
+ reduced = (stbi_uc *)stbi__malloc(img_len);
|
|
|
|
+ if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling
|
|
|
|
+
|
|
|
|
+ p->out = reduced;
|
|
|
|
+ STBI_FREE(orig);
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
static int stbi__unpremultiply_on_load = 0;
|
|
static int stbi__unpremultiply_on_load = 0;
|
|
static int stbi__de_iphone_flag = 0;
|
|
static int stbi__de_iphone_flag = 0;
|
|
|
|
|
|
@@ -4326,8 +4430,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
{
|
|
{
|
|
stbi_uc palette[1024], pal_img_n=0;
|
|
stbi_uc palette[1024], pal_img_n=0;
|
|
stbi_uc has_trans=0, tc[3];
|
|
stbi_uc has_trans=0, tc[3];
|
|
|
|
+ stbi__uint16 tc16[3];
|
|
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
|
|
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
|
|
- int first=1,k,interlace=0, color=0, depth=0, is_iphone=0;
|
|
|
|
|
|
+ int first=1,k,interlace=0, color=0, is_iphone=0;
|
|
stbi__context *s = z->s;
|
|
stbi__context *s = z->s;
|
|
|
|
|
|
z->expanded = NULL;
|
|
z->expanded = NULL;
|
|
@@ -4352,8 +4457,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
|
|
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
|
|
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
|
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
|
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
|
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
|
- depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only");
|
|
|
|
|
|
+ z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
|
|
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
|
|
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
|
|
|
|
+ if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
|
|
if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
|
|
if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
|
|
comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");
|
|
comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");
|
|
filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG");
|
|
filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG");
|
|
@@ -4401,8 +4507,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
|
|
if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
|
|
if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
|
|
if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
|
|
has_trans = 1;
|
|
has_trans = 1;
|
|
- for (k=0; k < s->img_n; ++k)
|
|
|
|
- tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger
|
|
|
|
|
|
+ if (z->depth == 16) {
|
|
|
|
+ for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is
|
|
|
|
+ } else {
|
|
|
|
+ for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
|
|
|
|
+ }
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -4418,6 +4527,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
|
|
if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
|
|
while (ioff + c.length > idata_limit)
|
|
while (ioff + c.length > idata_limit)
|
|
idata_limit *= 2;
|
|
idata_limit *= 2;
|
|
|
|
+ STBI_NOTUSED(idata_limit_old);
|
|
p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
|
p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
|
z->idata = p;
|
|
z->idata = p;
|
|
}
|
|
}
|
|
@@ -4432,7 +4542,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
if (scan != STBI__SCAN_load) return 1;
|
|
if (scan != STBI__SCAN_load) return 1;
|
|
if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
|
|
if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
|
|
// initial guess for decoded data size to avoid unnecessary reallocs
|
|
// initial guess for decoded data size to avoid unnecessary reallocs
|
|
- bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component
|
|
|
|
|
|
+ bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
|
|
raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
|
|
raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
|
|
z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
|
|
z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
|
|
if (z->expanded == NULL) return 0; // zlib should set error
|
|
if (z->expanded == NULL) return 0; // zlib should set error
|
|
@@ -4441,9 +4551,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
s->img_out_n = s->img_n+1;
|
|
s->img_out_n = s->img_n+1;
|
|
else
|
|
else
|
|
s->img_out_n = s->img_n;
|
|
s->img_out_n = s->img_n;
|
|
- if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0;
|
|
|
|
- if (has_trans)
|
|
|
|
- if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
|
|
|
|
|
|
+ if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
|
|
|
|
+ if (has_trans) {
|
|
|
|
+ if (z->depth == 16) {
|
|
|
|
+ if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
|
|
|
|
+ } else {
|
|
|
|
+ if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
|
|
if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
|
|
stbi__de_iphone(z);
|
|
stbi__de_iphone(z);
|
|
if (pal_img_n) {
|
|
if (pal_img_n) {
|
|
@@ -4485,6 +4600,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
|
|
unsigned char *result=NULL;
|
|
unsigned char *result=NULL;
|
|
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
|
|
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
|
|
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
|
|
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
|
|
|
|
+ if (p->depth == 16) {
|
|
|
|
+ if (!stbi__reduce_png(p)) {
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
result = p->out;
|
|
result = p->out;
|
|
p->out = NULL;
|
|
p->out = NULL;
|
|
if (req_comp && req_comp != p->s->img_out_n) {
|
|
if (req_comp && req_comp != p->s->img_out_n) {
|
|
@@ -4494,7 +4614,7 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
|
|
}
|
|
}
|
|
*x = p->s->img_x;
|
|
*x = p->s->img_x;
|
|
*y = p->s->img_y;
|
|
*y = p->s->img_y;
|
|
- if (n) *n = p->s->img_out_n;
|
|
|
|
|
|
+ if (n) *n = p->s->img_n;
|
|
}
|
|
}
|
|
STBI_FREE(p->out); p->out = NULL;
|
|
STBI_FREE(p->out); p->out = NULL;
|
|
STBI_FREE(p->expanded); p->expanded = NULL;
|
|
STBI_FREE(p->expanded); p->expanded = NULL;
|
|
@@ -4619,6 +4739,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
|
|
stbi__get16le(s); // discard reserved
|
|
stbi__get16le(s); // discard reserved
|
|
info->offset = stbi__get32le(s);
|
|
info->offset = stbi__get32le(s);
|
|
info->hsz = hsz = stbi__get32le(s);
|
|
info->hsz = hsz = stbi__get32le(s);
|
|
|
|
+ info->mr = info->mg = info->mb = info->ma = 0;
|
|
|
|
|
|
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
|
|
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
|
|
if (hsz == 12) {
|
|
if (hsz == 12) {
|
|
@@ -4647,7 +4768,6 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
|
|
stbi__get32le(s);
|
|
stbi__get32le(s);
|
|
}
|
|
}
|
|
if (info->bpp == 16 || info->bpp == 32) {
|
|
if (info->bpp == 16 || info->bpp == 32) {
|
|
- info->mr = info->mg = info->mb = 0;
|
|
|
|
if (compress == 0) {
|
|
if (compress == 0) {
|
|
if (info->bpp == 32) {
|
|
if (info->bpp == 32) {
|
|
info->mr = 0xffu << 16;
|
|
info->mr = 0xffu << 16;
|
|
@@ -5342,6 +5462,21 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (channelCount >= 4) {
|
|
|
|
+ for (i=0; i < w*h; ++i) {
|
|
|
|
+ unsigned char *pixel = out + 4*i;
|
|
|
|
+ if (pixel[3] != 0 && pixel[3] != 255) {
|
|
|
|
+ // remove weird white matte from PSD
|
|
|
|
+ float a = pixel[3] / 255.0f;
|
|
|
|
+ float ra = 1.0f / a;
|
|
|
|
+ float inv_a = 255.0f * (1 - ra);
|
|
|
|
+ pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
|
|
|
|
+ pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
|
|
|
|
+ pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if (req_comp && req_comp != 4) {
|
|
if (req_comp && req_comp != 4) {
|
|
out = stbi__convert_format(out, 4, req_comp, w, h);
|
|
out = stbi__convert_format(out, 4, req_comp, w, h);
|
|
if (out == NULL) return out; // stbi__convert_format frees input on failure
|
|
if (out == NULL) return out; // stbi__convert_format frees input on failure
|
|
@@ -5654,13 +5789,15 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
|
|
|
|
|
|
static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
|
|
static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
|
|
{
|
|
{
|
|
- stbi__gif g;
|
|
|
|
- if (!stbi__gif_header(s, &g, comp, 1)) {
|
|
|
|
|
|
+ stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
|
|
|
|
+ if (!stbi__gif_header(s, g, comp, 1)) {
|
|
|
|
+ STBI_FREE(g);
|
|
stbi__rewind( s );
|
|
stbi__rewind( s );
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- if (x) *x = g.w;
|
|
|
|
- if (y) *y = g.h;
|
|
|
|
|
|
+ if (x) *x = g->w;
|
|
|
|
+ if (y) *y = g->h;
|
|
|
|
+ STBI_FREE(g);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5913,20 +6050,20 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
|
|
static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
|
static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
|
{
|
|
{
|
|
stbi_uc *u = 0;
|
|
stbi_uc *u = 0;
|
|
- stbi__gif g;
|
|
|
|
- memset(&g, 0, sizeof(g));
|
|
|
|
|
|
+ stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
|
|
|
|
+ memset(g, 0, sizeof(*g));
|
|
|
|
|
|
- u = stbi__gif_load_next(s, &g, comp, req_comp);
|
|
|
|
|
|
+ u = stbi__gif_load_next(s, g, comp, req_comp);
|
|
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
|
|
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
|
|
if (u) {
|
|
if (u) {
|
|
- *x = g.w;
|
|
|
|
- *y = g.h;
|
|
|
|
|
|
+ *x = g->w;
|
|
|
|
+ *y = g->h;
|
|
if (req_comp && req_comp != 4)
|
|
if (req_comp && req_comp != 4)
|
|
- u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
|
|
|
|
|
|
+ u = stbi__convert_format(u, 4, req_comp, g->w, g->h);
|
|
}
|
|
}
|
|
- else if (g.out)
|
|
|
|
- STBI_FREE(g.out);
|
|
|
|
-
|
|
|
|
|
|
+ else if (g->out)
|
|
|
|
+ STBI_FREE(g->out);
|
|
|
|
+ STBI_FREE(g);
|
|
return u;
|
|
return u;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6464,6 +6601,14 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
|
|
|
|
|
|
/*
|
|
/*
|
|
revision history:
|
|
revision history:
|
|
|
|
+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
|
|
|
|
+ 2.11 (2016-04-02) allocate large structures on the stack
|
|
|
|
+ remove white matting for transparent PSD
|
|
|
|
+ fix reported channel count for PNG & BMP
|
|
|
|
+ re-enable SSE2 in non-gcc 64-bit
|
|
|
|
+ support RGB-formatted JPEG
|
|
|
|
+ read 16-bit PNGs (only as 8-bit)
|
|
|
|
+ 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
|
|
2.09 (2016-01-16) allow comments in PNM files
|
|
2.09 (2016-01-16) allow comments in PNM files
|
|
16-bit-per-pixel TGA (not bit-per-component)
|
|
16-bit-per-pixel TGA (not bit-per-component)
|
|
info() for TGA could break due to .hdr handling
|
|
info() for TGA could break due to .hdr handling
|