Update stb libs to latest version

This commit is contained in:
raysan5 2016-04-06 17:45:25 +02:00
parent 1a2a44200a
commit 3b67a4cfba
7 changed files with 349 additions and 248 deletions

View File

@ -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 Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan
Ryamond Barbiero Paul Du Bois Engin Manap 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 This software is dual-licensed to the public domain and under the following
recognized, you are granted a perpetual, irrevocable license to copy, license: you are granted a perpetual, irrevocable license to copy, modify,
distribute, and modify this file as you see fit. 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! if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files!
return stbi__err("bad component ID","Corrupt JPEG"); // 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; unsigned char* result;
j.s = s; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
stbi__setup_jpeg(&j); j->s = s;
return load_jpeg_image(&j, x,y,comp,req_comp); 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; int result;
j.s = s; stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
return stbi__jpeg_info_raw(&j, x, y, comp); 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 (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
for (k=0; k < img_n; ++k) 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_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-out_n],prior[k],prior[k-out_n])); 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-out_n] >> 1)); 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-out_n],0,0)); 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) if (z->depth == 16) {
tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger 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 (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
if (has_trans) if (has_trans) {
if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; 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; stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
if (!stbi__gif_header(s, &g, comp, 1)) { 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 (x) *x = g->w;
if (y) *y = g.h; 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; stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
memset(&g, 0, sizeof(g)); 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; *x = g->w;
*y = g.h; *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) else if (g->out)
STBI_FREE(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

View File

@ -1,4 +1,4 @@
/* stb_image_resize - v0.90 - public domain image resizing /* stb_image_resize - v0.91 - public domain image resizing
by Jorge L Rodriguez (@VinoBS) - 2014 by Jorge L Rodriguez (@VinoBS) - 2014
http://github.com/nothings/stb http://github.com/nothings/stb
@ -156,13 +156,14 @@
Sean Barrett: API design, optimizations Sean Barrett: API design, optimizations
REVISIONS REVISIONS
0.91 (2016-04-02) fix warnings; fix handling of subpixel regions
0.90 (2014-09-17) first released version 0.90 (2014-09-17) first released version
LICENSE LICENSE
This software is in the public domain. Where that dedication is not This software is dual-licensed to the public domain and under the following
recognized, you are granted a perpetual, irrevocable license to copy, license: you are granted a perpetual, irrevocable license to copy, modify,
distribute, and modify this file as you see fit. publish, and distribute this file as you see fit.
TODO TODO
Don't decode all of the image data when only processing a partial tile Don't decode all of the image data when only processing a partial tile
@ -383,15 +384,6 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int
#define STBIR_ASSERT(x) assert(x) #define STBIR_ASSERT(x) assert(x)
#endif #endif
#ifdef STBIR_DEBUG
#define STBIR__DEBUG_ASSERT STBIR_ASSERT
#else
#define STBIR__DEBUG_ASSERT
#endif
// If you hit this it means I haven't done it yet.
#define STBIR__UNIMPLEMENTED(x) STBIR_ASSERT(!(x))
// For memset // For memset
#include <string.h> #include <string.h>
@ -758,7 +750,7 @@ static float stbir__filter_trapezoid(float x, float scale)
{ {
float halfscale = scale / 2; float halfscale = scale / 2;
float t = 0.5f + halfscale; float t = 0.5f + halfscale;
STBIR__DEBUG_ASSERT(scale <= 1); STBIR_ASSERT(scale <= 1);
x = (float)fabs(x); x = (float)fabs(x);
@ -776,7 +768,7 @@ static float stbir__filter_trapezoid(float x, float scale)
static float stbir__support_trapezoid(float scale) static float stbir__support_trapezoid(float scale)
{ {
STBIR__DEBUG_ASSERT(scale <= 1); STBIR_ASSERT(scale <= 1);
return 0.5f + scale / 2; return 0.5f + scale / 2;
} }
@ -990,7 +982,7 @@ static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max)
return n; // NOTREACHED return n; // NOTREACHED
default: default:
STBIR__UNIMPLEMENTED("Unimplemented edge type"); STBIR_ASSERT(!"Unimplemented edge type");
return 0; return 0;
} }
} }
@ -1039,12 +1031,12 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi
float total_filter = 0; float total_filter = 0;
float filter_scale; float filter_scale;
STBIR__DEBUG_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
contributor->n0 = in_first_pixel; contributor->n0 = in_first_pixel;
contributor->n1 = in_last_pixel; contributor->n1 = in_last_pixel;
STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0); STBIR_ASSERT(contributor->n1 >= contributor->n0);
for (i = 0; i <= in_last_pixel - in_first_pixel; i++) for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
{ {
@ -1062,10 +1054,10 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi
total_filter += coefficient_group[i]; total_filter += coefficient_group[i];
} }
STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0);
STBIR__DEBUG_ASSERT(total_filter > 0.9); STBIR_ASSERT(total_filter > 0.9);
STBIR__DEBUG_ASSERT(total_filter < 1.1f); // Make sure it's not way off. STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off.
// Make sure the sum of all coefficients is 1. // Make sure the sum of all coefficients is 1.
filter_scale = 1 / total_filter; filter_scale = 1 / total_filter;
@ -1087,12 +1079,12 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st
{ {
int i; int i;
STBIR__DEBUG_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
contributor->n0 = out_first_pixel; contributor->n0 = out_first_pixel;
contributor->n1 = out_last_pixel; contributor->n1 = out_last_pixel;
STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0); STBIR_ASSERT(contributor->n1 >= contributor->n0);
for (i = 0; i <= out_last_pixel - out_first_pixel; i++) for (i = 0; i <= out_last_pixel - out_first_pixel; i++)
{ {
@ -1101,7 +1093,7 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st
coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio;
} }
STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);
for (i = out_last_pixel - out_first_pixel; i >= 0; i--) for (i = out_last_pixel - out_first_pixel; i >= 0; i--)
{ {
@ -1136,8 +1128,8 @@ static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, st
break; break;
} }
STBIR__DEBUG_ASSERT(total > 0.9f); STBIR_ASSERT(total > 0.9f);
STBIR__DEBUG_ASSERT(total < 1.1f); STBIR_ASSERT(total < 1.1f);
scale = 1 / total; scale = 1 / total;
@ -1364,7 +1356,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n)
break; break;
default: default:
STBIR__UNIMPLEMENTED("Unknown type/colorspace/channels combination."); STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");
break; break;
} }
@ -1425,7 +1417,7 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n)
else else
{ {
ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width; ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width;
STBIR__DEBUG_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
} }
ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float));
@ -1457,11 +1449,11 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
int coefficient_group = coefficient_width * x; int coefficient_group = coefficient_width * x;
int coefficient_counter = 0; int coefficient_counter = 0;
STBIR__DEBUG_ASSERT(n1 >= n0); STBIR_ASSERT(n1 >= n0);
STBIR__DEBUG_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin);
STBIR__DEBUG_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin);
STBIR__DEBUG_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
STBIR__DEBUG_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
switch (channels) { switch (channels) {
case 1: case 1:
@ -1469,7 +1461,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
{ {
int in_pixel_index = k * 1; int in_pixel_index = k * 1;
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
} }
break; break;
@ -1478,7 +1470,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
{ {
int in_pixel_index = k * 2; int in_pixel_index = k * 2;
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
} }
@ -1488,7 +1480,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
{ {
int in_pixel_index = k * 3; int in_pixel_index = k * 3;
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
@ -1499,7 +1491,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
{ {
int in_pixel_index = k * 4; int in_pixel_index = k * 4;
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
@ -1512,7 +1504,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
int in_pixel_index = k * channels; int in_pixel_index = k * channels;
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
int c; int c;
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
for (c = 0; c < channels; c++) for (c = 0; c < channels; c++)
output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
} }
@ -1535,7 +1527,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin;
int max_x = input_w + filter_pixel_margin * 2; int max_x = input_w + filter_pixel_margin * 2;
STBIR__DEBUG_ASSERT(!stbir__use_width_upsampling(stbir_info)); STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info));
switch (channels) { switch (channels) {
case 1: case 1:
@ -1553,7 +1545,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
{ {
int out_pixel_index = k * 1; int out_pixel_index = k * 1;
float coefficient = horizontal_coefficients[coefficient_group + k - n0]; float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
} }
} }
@ -1574,7 +1566,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
{ {
int out_pixel_index = k * 2; int out_pixel_index = k * 2;
float coefficient = horizontal_coefficients[coefficient_group + k - n0]; float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
} }
@ -1596,7 +1588,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
{ {
int out_pixel_index = k * 3; int out_pixel_index = k * 3;
float coefficient = horizontal_coefficients[coefficient_group + k - n0]; float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
@ -1619,7 +1611,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
{ {
int out_pixel_index = k * 4; int out_pixel_index = k * 4;
float coefficient = horizontal_coefficients[coefficient_group + k - n0]; float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
@ -1644,7 +1636,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
int c; int c;
int out_pixel_index = k * channels; int out_pixel_index = k * channels;
float coefficient = horizontal_coefficients[coefficient_group + k - n0]; float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR__DEBUG_ASSERT(coefficient != 0); STBIR_ASSERT(coefficient != 0);
for (c = 0; c < channels; c++) for (c = 0; c < channels; c++)
output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
} }
@ -1856,7 +1848,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
break; break;
default: default:
STBIR__UNIMPLEMENTED("Unknown type/colorspace/channels combination."); STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");
break; break;
} }
} }
@ -1893,7 +1885,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
output_row_start = n * stbir_info->output_stride_bytes; output_row_start = n * stbir_info->output_stride_bytes;
STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info)); STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));
memset(encode_buffer, 0, output_w * sizeof(float) * channels); memset(encode_buffer, 0, output_w * sizeof(float) * channels);
@ -2003,7 +1995,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n,
n0 = vertical_contributors[contributor].n0; n0 = vertical_contributors[contributor].n0;
n1 = vertical_contributors[contributor].n1; n1 = vertical_contributors[contributor].n1;
STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info)); STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));
for (k = n0; k <= n1; k++) for (k = n0; k <= n1; k++)
{ {
@ -2068,7 +2060,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
float scale_ratio = stbir_info->vertical_scale; float scale_ratio = stbir_info->vertical_scale;
float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio;
STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info)); STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));
for (y = 0; y < stbir_info->output_h; y++) for (y = 0; y < stbir_info->output_h; y++)
{ {
@ -2077,7 +2069,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out);
STBIR__DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width); STBIR_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width);
if (stbir_info->ring_buffer_begin_index >= 0) if (stbir_info->ring_buffer_begin_index >= 0)
{ {
@ -2169,7 +2161,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
int pixel_margin = stbir_info->vertical_filter_pixel_margin; int pixel_margin = stbir_info->vertical_filter_pixel_margin;
int max_y = stbir_info->input_h + pixel_margin; int max_y = stbir_info->input_h + pixel_margin;
STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info)); STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));
for (y = -pixel_margin; y < max_y; y++) for (y = -pixel_margin; y < max_y; y++)
{ {
@ -2178,7 +2170,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in);
STBIR__DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width); STBIR_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width);
if (out_last_scanline < 0 || out_first_scanline >= output_h) if (out_last_scanline < 0 || out_first_scanline >= output_h)
continue; continue;
@ -2229,8 +2221,8 @@ static void stbir__calculate_transform(stbir__info *info, float s0, float t0, fl
info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0);
info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0);
info->horizontal_shift = s0 * info->input_w / (s1 - s0); info->horizontal_shift = s0 * info->output_w / (s1 - s0);
info->vertical_shift = t0 * info->input_h / (t1 - t0); info->vertical_shift = t0 * info->output_h / (t1 - t0);
} }
} }
@ -2380,7 +2372,7 @@ static int stbir__resize_allocated(stbir__info *info,
info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float);
info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float);
STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
} }
else else
{ {
@ -2388,7 +2380,7 @@ static int stbir__resize_allocated(stbir__info *info,
info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float);
info->encode_buffer = NULL; info->encode_buffer = NULL;
STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
} }
#undef STBIR__NEXT_MEMPTR #undef STBIR__NEXT_MEMPTR
@ -2409,10 +2401,10 @@ static int stbir__resize_allocated(stbir__info *info,
STBIR_PROGRESS_REPORT(1); STBIR_PROGRESS_REPORT(1);
#ifdef STBIR_DEBUG_OVERWRITE_TEST #ifdef STBIR_DEBUG_OVERWRITE_TEST
STBIR__DEBUG_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
STBIR__DEBUG_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0);
STBIR__DEBUG_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
STBIR__DEBUG_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0);
#endif #endif
return 1; return 1;

View File

@ -1,4 +1,4 @@
/* stb_image_write - v1.01 - public domain - http://nothings.org/stb/stb_image_write.h /* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h
writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
no warranty implied; use at your own risk no warranty implied; use at your own risk
@ -102,12 +102,13 @@ CREDITS:
Sergio Gonzalez Sergio Gonzalez
Jonas Karlsson Jonas Karlsson
Filip Wasil Filip Wasil
Thatcher Ulrich
LICENSE LICENSE
This software is in the public domain. Where that dedication is not This software is dual-licensed to the public domain and under the following
recognized, you are granted a perpetual, irrevocable license to copy, license: you are granted a perpetual, irrevocable license to copy, modify,
distribute, and modify this file as you see fit. publish, and distribute this file as you see fit.
*/ */
@ -736,7 +737,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
unsigned int bitbuf=0; unsigned int bitbuf=0;
int i,j, bitcount=0; int i,j, bitcount=0;
unsigned char *out = NULL; unsigned char *out = NULL;
unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack! unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
if (quality < 5) quality = 5; if (quality < 5) quality = 5;
stbiw__sbpush(out, 0x78); // DEFLATE 32K window stbiw__sbpush(out, 0x78); // DEFLATE 32K window
@ -808,6 +809,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
for (i=0; i < stbiw__ZHASH; ++i) for (i=0; i < stbiw__ZHASH; ++i)
(void) stbiw__sbfree(hash_table[i]); (void) stbiw__sbfree(hash_table[i]);
STBIW_FREE(hash_table);
{ {
// compute adler32 on input // compute adler32 on input
@ -1015,6 +1017,8 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x,
#endif // STB_IMAGE_WRITE_IMPLEMENTATION #endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history /* Revision history
1.02 (2016-04-02)
avoid allocating large structures on the stack
1.01 (2016-01-16) 1.01 (2016-01-16)
STBIW_REALLOC_SIZED: support allocators with no realloc support STBIW_REALLOC_SIZED: support allocators with no realloc support
avoid race-condition in crc initialization avoid race-condition in crc initialization

View File

@ -1,4 +1,4 @@
// stb_rect_pack.h - v0.06 - public domain - rectangle packing // stb_rect_pack.h - v0.08 - public domain - rectangle packing
// Sean Barrett 2014 // Sean Barrett 2014
// //
// Useful for e.g. packing rectangular textures into an atlas. // Useful for e.g. packing rectangular textures into an atlas.
@ -28,14 +28,22 @@
// Minor features // Minor features
// Martins Mozeiko // Martins Mozeiko
// Bugfixes / warning fixes // Bugfixes / warning fixes
// [your name could be here] // Jeremy Jaussaud
// //
// Version history: // Version history:
// //
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert // 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support // 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release // 0.01: initial release
//
// LICENSE
//
// 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.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -541,12 +549,16 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) { for (i=0; i < num_rects; ++i) {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); if (rects[i].w == 0 || rects[i].h == 0) {
if (fr.prev_link) { rects[i].x = rects[i].y = 0; // empty rect needs no space
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else { } else {
rects[i].x = rects[i].y = STBRP__MAXVAL; stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
} }
} }

View File

@ -1,4 +1,4 @@
// stb_truetype.h - v1.09 - public domain // stb_truetype.h - v1.11 - public domain
// authored from 2009-2015 by Sean Barrett / RAD Game Tools // authored from 2009-2015 by Sean Barrett / RAD Game Tools
// //
// This library processes TrueType files: // This library processes TrueType files:
@ -21,6 +21,10 @@
// Mikko Mononen: compound shape support, more cmap formats // Mikko Mononen: compound shape support, more cmap formats
// Tor Andersson: kerning, subpixel rendering // Tor Andersson: kerning, subpixel rendering
// //
// Misc other:
// Ryan Gordon
// Simon Glass
//
// Bug/warning reports/fixes: // Bug/warning reports/fixes:
// "Zer" on mollyrocket (with fix) // "Zer" on mollyrocket (with fix)
// Cass Everitt // Cass Everitt
@ -45,11 +49,10 @@
// Thomas Fields // Thomas Fields
// Derek Vinyard // Derek Vinyard
// //
// Misc other:
// Ryan Gordon
//
// VERSION HISTORY // VERSION HISTORY
// //
// 1.11 (2016-04-02) fix unused-variable warning
// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
@ -68,9 +71,9 @@
// //
// LICENSE // LICENSE
// //
// This software is in the public domain. Where that dedication is not // This software is dual-licensed to the public domain and under the following
// recognized, you are granted a perpetual, irrevocable license to copy, // license: you are granted a perpetual, irrevocable license to copy, modify,
// distribute, and modify this file as you see fit. // publish, and distribute this file as you see fit.
// //
// USAGE // USAGE
// //
@ -406,6 +409,11 @@ int main(int arg, char **argv)
#define STBTT_sqrt(x) sqrt(x) #define STBTT_sqrt(x) sqrt(x)
#endif #endif
#ifndef STBTT_fabs
#include <math.h>
#define STBTT_fabs(x) fabs(x)
#endif
// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
#ifndef STBTT_malloc #ifndef STBTT_malloc
#include <stdlib.h> #include <stdlib.h>
@ -629,7 +637,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
// The following structure is defined publically so you can declare one on // The following structure is defined publically so you can declare one on
// the stack or as a global or etc, but you should treat it as opaque. // the stack or as a global or etc, but you should treat it as opaque.
typedef struct stbtt_fontinfo struct stbtt_fontinfo
{ {
void * userdata; void * userdata;
unsigned char * data; // pointer to .ttf file unsigned char * data; // pointer to .ttf file
@ -640,7 +648,7 @@ typedef struct stbtt_fontinfo
int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph int indexToLocFormat; // format needed to map from glyph index to glyph
} stbtt_fontinfo; };
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
// Given an offset into the file that defines a font, this function builds // Given an offset into the file that defines a font, this function builds
@ -942,6 +950,12 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS
#define STBTT_RASTERIZER_VERSION 2 #define STBTT_RASTERIZER_VERSION 2
#endif #endif
#ifdef _MSC_VER
#define STBTT__NOTUSED(v) (void)(v)
#else
#define STBTT__NOTUSED(v) (void)sizeof(v)
#endif
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// //
// accessors to parse data from file // accessors to parse data from file
@ -1993,7 +2007,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
} }
y_crossing += dy * (x2 - (x1+1)); y_crossing += dy * (x2 - (x1+1));
STBTT_assert(fabs(area) <= 1.01f); STBTT_assert(STBTT_fabs(area) <= 1.01f);
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
@ -2071,6 +2085,8 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
int y,j=0, i; int y,j=0, i;
float scanline_data[129], *scanline, *scanline2; float scanline_data[129], *scanline, *scanline2;
STBTT__NOTUSED(vsubsample);
if (result->w > 64) if (result->w > 64)
scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
else else
@ -2129,7 +2145,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
int m; int m;
sum += scanline2[i]; sum += scanline2[i];
k = scanline[i] + sum; k = scanline[i] + sum;
k = (float) fabs(k)*255 + 0.5f; k = (float) STBTT_fabs(k)*255 + 0.5f;
m = (int) k; m = (int) k;
if (m > 255) m = 255; if (m > 255) m = 255;
result->pixels[j*result->stride + i] = (unsigned char) m; result->pixels[j*result->stride + i] = (unsigned char) m;
@ -2430,7 +2446,10 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
if (scale_x == 0) scale_x = scale_y; if (scale_x == 0) scale_x = scale_y;
if (scale_y == 0) { if (scale_y == 0) {
if (scale_x == 0) return NULL; if (scale_x == 0) {
STBTT_free(vertices, info->userdata);
return NULL;
}
scale_y = scale_x; scale_y = scale_x;
} }
@ -2586,11 +2605,6 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int
// //
#ifndef STB_RECT_PACK_VERSION #ifndef STB_RECT_PACK_VERSION
#ifdef _MSC_VER
#define STBTT__NOTUSED(v) (void)(v)
#else
#define STBTT__NOTUSED(v) (void)sizeof(v)
#endif
typedef int stbrp_coord; typedef int stbrp_coord;
@ -3205,6 +3219,10 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const
// FULL VERSION HISTORY // FULL VERSION HISTORY
// //
// 1.11 (2016-04-02) fix unused-variable warning
// 1.10 (2016-04-02) allow user-defined fabs() replacement
// fix memory leak if fontsize=0.0
// fix warning from duplicate typedef
// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;

View File

@ -168,6 +168,9 @@
#include <math.h> #include <math.h>
#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh))
#include <malloc.h> #include <malloc.h>
#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__)
#include <alloca.h>
#endif
#endif #endif
#else // STB_VORBIS_NO_CRT #else // STB_VORBIS_NO_CRT
#define NULL 0 #define NULL 0
@ -1484,85 +1487,6 @@ static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **out
return TRUE; return TRUE;
} }
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **outputs, int *c_inter_p, int *p_inter_p, int len, int total_decode)
{
int c_inter = *c_inter_p;
int p_inter = *p_inter_p;
int i,z, effective = c->dimensions;
// type 0 is only legal in a scalar context
if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream);
while (total_decode > 0) {
float last = CODEBOOK_ELEMENT_BASE(c);
DECODE_VQ(z,f,c);
if (z < 0) {
if (!f->bytes_in_seg)
if (f->last_seg) return FALSE;
return error(f, VORBIS_invalid_stream);
}
// if this will take us off the end of the buffers, stop short!
// we check by computing the length of the virtual interleaved
// buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter),
// and the length we'll be using (effective)
if (c_inter + p_inter*2 + effective > len * 2) {
effective = len*2 - (p_inter*2 - c_inter);
}
{
z *= c->dimensions;
if (c->sequence_p) {
// haven't optimized this case because I don't have any examples
for (i=0; i < effective; ++i) {
float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
if (outputs[c_inter])
outputs[c_inter][p_inter] += val;
if (++c_inter == 2) { c_inter = 0; ++p_inter; }
last = val;
}
} else {
i=0;
if (c_inter == 1 && i < effective) {
float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
if (outputs[c_inter])
outputs[c_inter][p_inter] += val;
c_inter = 0; ++p_inter;
++i;
}
{
float *z0 = outputs[0];
float *z1 = outputs[1];
for (; i+1 < effective;) {
float v0 = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
float v1 = CODEBOOK_ELEMENT_FAST(c,z+i+1) + last;
if (z0)
z0[p_inter] += v0;
if (z1)
z1[p_inter] += v1;
++p_inter;
i += 2;
}
}
if (i < effective) {
float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
if (outputs[c_inter])
outputs[c_inter][p_inter] += val;
if (++c_inter == 2) { c_inter = 0; ++p_inter; }
}
}
}
total_decode -= effective;
}
*c_inter_p = c_inter;
*p_inter_p = p_inter;
return TRUE;
}
#endif
static int predict_point(int x, int x0, int x1, int y0, int y1) static int predict_point(int x, int x0, int x1, int y0, int y1)
{ {
int dy = y1 - y0; int dy = y1 - y0;
@ -1941,6 +1865,11 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
} }
done: done:
CHECK(f); CHECK(f);
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
temp_free(f,part_classdata);
#else
temp_free(f,classifications);
#endif
temp_alloc_restore(f,temp_alloc_point); temp_alloc_restore(f,temp_alloc_point);
} }
@ -2586,6 +2515,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
} }
} }
temp_free(f,buf2);
temp_alloc_restore(f,save_point); temp_alloc_restore(f,save_point);
} }
@ -3499,7 +3429,6 @@ static int start_decoder(vorb *f)
} }
} }
} }
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
c->lookup_type = 2; c->lookup_type = 2;
} }
else else
@ -3515,11 +3444,11 @@ static int start_decoder(vorb *f)
if (c->sequence_p) if (c->sequence_p)
last = val; last = val;
} }
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
} }
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
skip:; skip:;
#endif #endif
setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
CHECK(f); CHECK(f);
} }
@ -4045,7 +3974,7 @@ int stb_vorbis_decode_frame_pushdata(
while (get8_packet(f) != EOP) while (get8_packet(f) != EOP)
if (f->eof) break; if (f->eof) break;
*samples = 0; *samples = 0;
return f->stream - data; return (int) (f->stream - data);
} }
if (error == VORBIS_continued_packet_flag_invalid) { if (error == VORBIS_continued_packet_flag_invalid) {
if (f->previous_length == 0) { if (f->previous_length == 0) {
@ -4055,7 +3984,7 @@ int stb_vorbis_decode_frame_pushdata(
while (get8_packet(f) != EOP) while (get8_packet(f) != EOP)
if (f->eof) break; if (f->eof) break;
*samples = 0; *samples = 0;
return f->stream - data; return (int) (f->stream - data);
} }
} }
// if we get an error while parsing, what to do? // if we get an error while parsing, what to do?
@ -4075,7 +4004,7 @@ int stb_vorbis_decode_frame_pushdata(
if (channels) *channels = f->channels; if (channels) *channels = f->channels;
*samples = len; *samples = len;
*output = f->outputs; *output = f->outputs;
return f->stream - data; return (int) (f->stream - data);
} }
stb_vorbis *stb_vorbis_open_pushdata( stb_vorbis *stb_vorbis_open_pushdata(
@ -4098,7 +4027,7 @@ stb_vorbis *stb_vorbis_open_pushdata(
f = vorbis_alloc(&p); f = vorbis_alloc(&p);
if (f) { if (f) {
*f = p; *f = p;
*data_used = f->stream - data; *data_used = (int) (f->stream - data);
*error = 0; *error = 0;
return f; return f;
} else { } else {
@ -4113,9 +4042,9 @@ unsigned int stb_vorbis_get_file_offset(stb_vorbis *f)
#ifndef STB_VORBIS_NO_PUSHDATA_API #ifndef STB_VORBIS_NO_PUSHDATA_API
if (f->push_mode) return 0; if (f->push_mode) return 0;
#endif #endif
if (USE_MEMORY(f)) return f->stream - f->stream_start; if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start);
#ifndef STB_VORBIS_NO_STDIO #ifndef STB_VORBIS_NO_STDIO
return ftell(f->f) - f->f_start; return (unsigned int) (ftell(f->f) - f->f_start);
#endif #endif
} }
@ -4611,7 +4540,7 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er
stb_vorbis *f, p; stb_vorbis *f, p;
vorbis_init(&p, alloc); vorbis_init(&p, alloc);
p.f = file; p.f = file;
p.f_start = ftell(file); p.f_start = (uint32) ftell(file);
p.stream_len = length; p.stream_len = length;
p.close_on_free = close_on_free; p.close_on_free = close_on_free;
if (start_decoder(&p)) { if (start_decoder(&p)) {
@ -4630,9 +4559,9 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er
stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc)
{ {
unsigned int len, start; unsigned int len, start;
start = ftell(file); start = (unsigned int) ftell(file);
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
len = ftell(file) - start; len = (unsigned int) (ftell(file) - start);
fseek(file, start, SEEK_SET); fseek(file, start, SEEK_SET);
return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len);
} }
@ -5027,6 +4956,9 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
#endif // STB_VORBIS_NO_PULLDATA_API #endif // STB_VORBIS_NO_PULLDATA_API
/* Version history /* Version history
1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version
1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks;
avoid discarding last frame of audio data
1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API
some more crash fixes when out of memory or with corrupt files some more crash fixes when out of memory or with corrupt files
1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)

View File

@ -1,4 +1,4 @@
// Ogg Vorbis audio decoder - v1.07 - public domain // Ogg Vorbis audio decoder - v1.09 - public domain
// http://nothings.org/stb_vorbis/ // http://nothings.org/stb_vorbis/
// //
// Original version written by Sean Barrett in 2007. // Original version written by Sean Barrett in 2007.
@ -9,9 +9,9 @@
// //
// LICENSE // LICENSE
// //
// This software is in the public domain. Where that dedication is not // This software is dual-licensed to the public domain and under the following
// recognized, you are granted a perpetual, irrevocable license to copy, // license: you are granted a perpetual, irrevocable license to copy, modify,
// distribute, and modify this file as you see fit. // publish, and distribute this file as you see fit.
// //
// No warranty for any purpose is expressed or implied by the author (nor // No warranty for any purpose is expressed or implied by the author (nor
// by RAD Game Tools). Report bugs and send enhancements to the author. // by RAD Game Tools). Report bugs and send enhancements to the author.
@ -31,11 +31,14 @@
// Terje Mathisen Niklas Frykholm Andy Hill // Terje Mathisen Niklas Frykholm Andy Hill
// Casey Muratori John Bolton Gargaj // Casey Muratori John Bolton Gargaj
// Laurent Gomila Marc LeBlanc Ronny Chevalier // Laurent Gomila Marc LeBlanc Ronny Chevalier
// Bernhard Wodo Evan Balster "alxprd"@github // Bernhard Wodo Evan Balster alxprd@github
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit // Phillip Bennefall Rohit Thiago Goulart
// manxorist@github saga musix
// //
// Partial history: // Partial history:
// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version
// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const // 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) // 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
// some crash fixes when out of memory or with corrupt files // some crash fixes when out of memory or with corrupt files
@ -72,11 +75,6 @@
#include "utils.h" // Android fopen function map #include "utils.h" // Android fopen function map
#endif #endif
// RaySan: Added for Linux
#ifdef __linux
#include <alloca.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif