mirror of
https://github.com/nothings/stb
synced 2024-12-15 12:22:55 +03:00
Merge branch 'working'
This commit is contained in:
commit
667d840860
499
stb_image.h
499
stb_image.h
@ -1,4 +1,4 @@
|
|||||||
/* stb_image - v2.08 - public domain image loader - http://nothings.org/stb_image.h
|
/* stb_image - v2.09 - 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,7 @@
|
|||||||
|
|
||||||
|
|
||||||
Latest revision history:
|
Latest revision history:
|
||||||
|
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
|
||||||
limited 16-bit PSD support
|
limited 16-bit PSD support
|
||||||
@ -175,44 +176,35 @@
|
|||||||
|
|
||||||
============================ Contributors =========================
|
============================ Contributors =========================
|
||||||
|
|
||||||
Image formats Bug fixes & warning fixes
|
Image formats Extensions, features
|
||||||
Sean Barrett (jpeg, png, bmp) Marc LeBlanc
|
Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info)
|
||||||
Nicolas Schulz (hdr, psd) Christpher Lloyd
|
Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info)
|
||||||
Jonathan Dummer (tga) Dave Moore
|
Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG)
|
||||||
Jean-Marc Lienher (gif) Won Chun
|
Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks)
|
||||||
Tom Seddon (pic) the Horde3D community
|
Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG)
|
||||||
Thatcher Ulrich (psd) Janez Zemva
|
Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)
|
||||||
Ken Miller (pgm, ppm) Jonathan Blow
|
Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)
|
||||||
urraka@github (animated gif) Laurent Gomila
|
urraka@github (animated gif) Junggon Kim (PNM comments)
|
||||||
Aruelien Pocheville
|
Daniel Gibson (16-bit TGA)
|
||||||
Ryamond Barbiero
|
|
||||||
David Woo
|
Optimizations & bugfixes
|
||||||
Extensions, features Martin Golini
|
Fabian "ryg" Giesen
|
||||||
Jetro Lauha (stbi_info) Roy Eltham
|
Arseny Kapoulkine
|
||||||
Martin "SpartanJ" Golini (stbi_info) Luke Graham
|
|
||||||
James "moose2000" Brown (iPhone PNG) Thomas Ruf
|
Bug & warning fixes
|
||||||
Ben "Disch" Wenger (io callbacks) John Bartholomew
|
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||||
Omar Cornut (1/2/4-bit PNG) Ken Hamada
|
Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson
|
||||||
Nicolas Guillemot (vertical flip) Cort Stratton
|
Dave Moore Roy Eltham Hayaki Saito Phil Jordan
|
||||||
Richard Mitton (16-bit PSD) Blazej Dariusz Roszkowski
|
Won Chun Luke Graham Johan Duparc Nathan Reed
|
||||||
Thibault Reuille
|
the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis
|
||||||
Paul Du Bois
|
Janez Zemva John Bartholomew Michal Cichon svdijk@github
|
||||||
Guillaume George
|
Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson
|
||||||
Jerry Jansson
|
Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github
|
||||||
Hayaki Saito
|
Aruelien Pocheville Thibault Reuille Cass Everitt
|
||||||
Johan Duparc
|
Ryamond Barbiero Paul Du Bois Engin Manap
|
||||||
Ronny Chevalier
|
Blazej Dariusz Roszkowski
|
||||||
Optimizations & bugfixes Michal Cichon
|
Michaelangel007@github
|
||||||
Fabian "ryg" Giesen Tero Hanninen
|
|
||||||
Arseny Kapoulkine Sergio Gonzalez
|
|
||||||
Cass Everitt
|
|
||||||
Engin Manap
|
|
||||||
If your name should be here but Martins Mozeiko
|
|
||||||
isn't, let Sean know. Joseph Thomson
|
|
||||||
Phil Jordan
|
|
||||||
Nathan Reed
|
|
||||||
Michaelangel007@github
|
|
||||||
Nick Verigakis
|
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
|
|
||||||
@ -461,12 +453,12 @@ STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y,
|
|||||||
#ifndef STBI_NO_HDR
|
#ifndef STBI_NO_HDR
|
||||||
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);
|
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);
|
||||||
STBIDEF void stbi_hdr_to_ldr_scale(float scale);
|
STBIDEF void stbi_hdr_to_ldr_scale(float scale);
|
||||||
#endif
|
#endif // STBI_NO_HDR
|
||||||
|
|
||||||
#ifndef STBI_NO_LINEAR
|
#ifndef STBI_NO_LINEAR
|
||||||
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);
|
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);
|
||||||
STBIDEF void stbi_ldr_to_hdr_scale(float scale);
|
STBIDEF void stbi_ldr_to_hdr_scale(float scale);
|
||||||
#endif // STBI_NO_HDR
|
#endif // STBI_NO_LINEAR
|
||||||
|
|
||||||
// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
|
// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
|
||||||
STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
|
STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
|
||||||
@ -630,18 +622,22 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
|
|||||||
#define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
|
#define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC)
|
#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
|
||||||
// ok
|
// ok
|
||||||
#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC)
|
#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)
|
||||||
// ok
|
// ok
|
||||||
#else
|
#else
|
||||||
#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC."
|
#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STBI_MALLOC
|
#ifndef STBI_MALLOC
|
||||||
#define STBI_MALLOC(sz) malloc(sz)
|
#define STBI_MALLOC(sz) malloc(sz)
|
||||||
#define STBI_REALLOC(p,sz) realloc(p,sz)
|
#define STBI_REALLOC(p,newsz) realloc(p,newsz)
|
||||||
#define STBI_FREE(p) free(p)
|
#define STBI_FREE(p) free(p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STBI_REALLOC_SIZED
|
||||||
|
#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// x86/x64 detection
|
// x86/x64 detection
|
||||||
@ -1186,14 +1182,15 @@ STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
|
#ifndef STBI_NO_LINEAR
|
||||||
static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
|
static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
|
||||||
|
|
||||||
#ifndef STBI_NO_LINEAR
|
|
||||||
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
|
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
|
||||||
STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
|
STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
|
||||||
|
|
||||||
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
|
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
|
||||||
STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
|
STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
|
||||||
|
|
||||||
@ -3616,14 +3613,14 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
|
|||||||
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
|
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
|
||||||
{
|
{
|
||||||
char *q;
|
char *q;
|
||||||
int cur, limit;
|
int cur, limit, old_limit;
|
||||||
z->zout = zout;
|
z->zout = zout;
|
||||||
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
|
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
|
||||||
cur = (int) (z->zout - z->zout_start);
|
cur = (int) (z->zout - z->zout_start);
|
||||||
limit = (int) (z->zout_end - z->zout_start);
|
limit = old_limit = (int) (z->zout_end - z->zout_start);
|
||||||
while (cur + n > limit)
|
while (cur + n > limit)
|
||||||
limit *= 2;
|
limit *= 2;
|
||||||
q = (char *) STBI_REALLOC(z->zout_start, limit);
|
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, 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;
|
||||||
@ -4408,11 +4405,12 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||||||
if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
|
if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
|
||||||
if ((int)(ioff + c.length) < (int)ioff) return 0;
|
if ((int)(ioff + c.length) < (int)ioff) return 0;
|
||||||
if (ioff + c.length > idata_limit) {
|
if (ioff + c.length > idata_limit) {
|
||||||
|
stbi__uint32 idata_limit_old = idata_limit;
|
||||||
stbi_uc *p;
|
stbi_uc *p;
|
||||||
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;
|
||||||
p = (stbi_uc *) STBI_REALLOC(z->idata, 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;
|
||||||
}
|
}
|
||||||
if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
|
if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
|
||||||
@ -4598,19 +4596,22 @@ static int stbi__shiftsigned(int v, int shift, int bits)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
typedef struct
|
||||||
{
|
{
|
||||||
stbi_uc *out;
|
int bpp, offset, hsz;
|
||||||
unsigned int mr=0,mg=0,mb=0,ma=0, all_a=255;
|
unsigned int mr,mg,mb,ma, all_a;
|
||||||
stbi_uc pal[256][4];
|
} stbi__bmp_data;
|
||||||
int psize=0,i,j,compress=0,width;
|
|
||||||
int bpp, flip_vertically, pad, target, offset, hsz;
|
static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
|
||||||
|
{
|
||||||
|
int hsz;
|
||||||
if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
|
if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
|
||||||
stbi__get32le(s); // discard filesize
|
stbi__get32le(s); // discard filesize
|
||||||
stbi__get16le(s); // discard reserved
|
stbi__get16le(s); // discard reserved
|
||||||
stbi__get16le(s); // discard reserved
|
stbi__get16le(s); // discard reserved
|
||||||
offset = stbi__get32le(s);
|
info->offset = stbi__get32le(s);
|
||||||
hsz = stbi__get32le(s);
|
info->hsz = hsz = stbi__get32le(s);
|
||||||
|
|
||||||
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) {
|
||||||
s->img_x = stbi__get16le(s);
|
s->img_x = stbi__get16le(s);
|
||||||
@ -4620,15 +4621,10 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
s->img_y = stbi__get32le(s);
|
s->img_y = stbi__get32le(s);
|
||||||
}
|
}
|
||||||
if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
|
if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
|
||||||
bpp = stbi__get16le(s);
|
info->bpp = stbi__get16le(s);
|
||||||
if (bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit");
|
if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit");
|
||||||
flip_vertically = ((int) s->img_y) > 0;
|
if (hsz != 12) {
|
||||||
s->img_y = abs((int) s->img_y);
|
int compress = stbi__get32le(s);
|
||||||
if (hsz == 12) {
|
|
||||||
if (bpp < 24)
|
|
||||||
psize = (offset - 14 - 24) / 3;
|
|
||||||
} else {
|
|
||||||
compress = stbi__get32le(s);
|
|
||||||
if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
|
if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
|
||||||
stbi__get32le(s); // discard sizeof
|
stbi__get32le(s); // discard sizeof
|
||||||
stbi__get32le(s); // discard hres
|
stbi__get32le(s); // discard hres
|
||||||
@ -4642,26 +4638,26 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
stbi__get32le(s);
|
stbi__get32le(s);
|
||||||
stbi__get32le(s);
|
stbi__get32le(s);
|
||||||
}
|
}
|
||||||
if (bpp == 16 || bpp == 32) {
|
if (info->bpp == 16 || info->bpp == 32) {
|
||||||
mr = mg = mb = 0;
|
info->mr = info->mg = info->mb = 0;
|
||||||
if (compress == 0) {
|
if (compress == 0) {
|
||||||
if (bpp == 32) {
|
if (info->bpp == 32) {
|
||||||
mr = 0xffu << 16;
|
info->mr = 0xffu << 16;
|
||||||
mg = 0xffu << 8;
|
info->mg = 0xffu << 8;
|
||||||
mb = 0xffu << 0;
|
info->mb = 0xffu << 0;
|
||||||
ma = 0xffu << 24;
|
info->ma = 0xffu << 24;
|
||||||
all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
|
info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
|
||||||
} else {
|
} else {
|
||||||
mr = 31u << 10;
|
info->mr = 31u << 10;
|
||||||
mg = 31u << 5;
|
info->mg = 31u << 5;
|
||||||
mb = 31u << 0;
|
info->mb = 31u << 0;
|
||||||
}
|
}
|
||||||
} else if (compress == 3) {
|
} else if (compress == 3) {
|
||||||
mr = stbi__get32le(s);
|
info->mr = stbi__get32le(s);
|
||||||
mg = stbi__get32le(s);
|
info->mg = stbi__get32le(s);
|
||||||
mb = stbi__get32le(s);
|
info->mb = stbi__get32le(s);
|
||||||
// not documented, but generated by photoshop and handled by mspaint
|
// not documented, but generated by photoshop and handled by mspaint
|
||||||
if (mr == mg && mg == mb) {
|
if (info->mr == info->mg && info->mg == info->mb) {
|
||||||
// ?!?!?
|
// ?!?!?
|
||||||
return stbi__errpuc("bad BMP", "bad BMP");
|
return stbi__errpuc("bad BMP", "bad BMP");
|
||||||
}
|
}
|
||||||
@ -4669,11 +4665,13 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
return stbi__errpuc("bad BMP", "bad BMP");
|
return stbi__errpuc("bad BMP", "bad BMP");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
STBI_ASSERT(hsz == 108 || hsz == 124);
|
int i;
|
||||||
mr = stbi__get32le(s);
|
if (hsz != 108 && hsz != 124)
|
||||||
mg = stbi__get32le(s);
|
return stbi__errpuc("bad BMP", "bad BMP");
|
||||||
mb = stbi__get32le(s);
|
info->mr = stbi__get32le(s);
|
||||||
ma = stbi__get32le(s);
|
info->mg = stbi__get32le(s);
|
||||||
|
info->mb = stbi__get32le(s);
|
||||||
|
info->ma = stbi__get32le(s);
|
||||||
stbi__get32le(s); // discard color space
|
stbi__get32le(s); // discard color space
|
||||||
for (i=0; i < 12; ++i)
|
for (i=0; i < 12; ++i)
|
||||||
stbi__get32le(s); // discard color space parameters
|
stbi__get32le(s); // discard color space parameters
|
||||||
@ -4684,35 +4682,68 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
stbi__get32le(s); // discard reserved
|
stbi__get32le(s); // discard reserved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bpp < 16)
|
|
||||||
psize = (offset - 14 - hsz) >> 2;
|
|
||||||
}
|
}
|
||||||
|
return (void *) 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
stbi_uc *out;
|
||||||
|
unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
|
||||||
|
stbi_uc pal[256][4];
|
||||||
|
int psize=0,i,j,width;
|
||||||
|
int flip_vertically, pad, target;
|
||||||
|
stbi__bmp_data info;
|
||||||
|
|
||||||
|
info.all_a = 255;
|
||||||
|
if (stbi__bmp_parse_header(s, &info) == NULL)
|
||||||
|
return NULL; // error code already set
|
||||||
|
|
||||||
|
flip_vertically = ((int) s->img_y) > 0;
|
||||||
|
s->img_y = abs((int) s->img_y);
|
||||||
|
|
||||||
|
mr = info.mr;
|
||||||
|
mg = info.mg;
|
||||||
|
mb = info.mb;
|
||||||
|
ma = info.ma;
|
||||||
|
all_a = info.all_a;
|
||||||
|
|
||||||
|
if (info.hsz == 12) {
|
||||||
|
if (info.bpp < 24)
|
||||||
|
psize = (info.offset - 14 - 24) / 3;
|
||||||
|
} else {
|
||||||
|
if (info.bpp < 16)
|
||||||
|
psize = (info.offset - 14 - info.hsz) >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
s->img_n = ma ? 4 : 3;
|
s->img_n = ma ? 4 : 3;
|
||||||
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
|
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
|
||||||
target = req_comp;
|
target = req_comp;
|
||||||
else
|
else
|
||||||
target = s->img_n; // if they want monochrome, we'll post-convert
|
target = s->img_n; // if they want monochrome, we'll post-convert
|
||||||
|
|
||||||
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y);
|
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y);
|
||||||
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
||||||
if (bpp < 16) {
|
if (info.bpp < 16) {
|
||||||
int z=0;
|
int z=0;
|
||||||
if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
|
if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
|
||||||
for (i=0; i < psize; ++i) {
|
for (i=0; i < psize; ++i) {
|
||||||
pal[i][2] = stbi__get8(s);
|
pal[i][2] = stbi__get8(s);
|
||||||
pal[i][1] = stbi__get8(s);
|
pal[i][1] = stbi__get8(s);
|
||||||
pal[i][0] = stbi__get8(s);
|
pal[i][0] = stbi__get8(s);
|
||||||
if (hsz != 12) stbi__get8(s);
|
if (info.hsz != 12) stbi__get8(s);
|
||||||
pal[i][3] = 255;
|
pal[i][3] = 255;
|
||||||
}
|
}
|
||||||
stbi__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4));
|
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
|
||||||
if (bpp == 4) width = (s->img_x + 1) >> 1;
|
if (info.bpp == 4) width = (s->img_x + 1) >> 1;
|
||||||
else if (bpp == 8) width = s->img_x;
|
else if (info.bpp == 8) width = s->img_x;
|
||||||
else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
|
else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
|
||||||
pad = (-width)&3;
|
pad = (-width)&3;
|
||||||
for (j=0; j < (int) s->img_y; ++j) {
|
for (j=0; j < (int) s->img_y; ++j) {
|
||||||
for (i=0; i < (int) s->img_x; i += 2) {
|
for (i=0; i < (int) s->img_x; i += 2) {
|
||||||
int v=stbi__get8(s),v2=0;
|
int v=stbi__get8(s),v2=0;
|
||||||
if (bpp == 4) {
|
if (info.bpp == 4) {
|
||||||
v2 = v & 15;
|
v2 = v & 15;
|
||||||
v >>= 4;
|
v >>= 4;
|
||||||
}
|
}
|
||||||
@ -4721,7 +4752,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
out[z++] = pal[v][2];
|
out[z++] = pal[v][2];
|
||||||
if (target == 4) out[z++] = 255;
|
if (target == 4) out[z++] = 255;
|
||||||
if (i+1 == (int) s->img_x) break;
|
if (i+1 == (int) s->img_x) break;
|
||||||
v = (bpp == 8) ? stbi__get8(s) : v2;
|
v = (info.bpp == 8) ? stbi__get8(s) : v2;
|
||||||
out[z++] = pal[v][0];
|
out[z++] = pal[v][0];
|
||||||
out[z++] = pal[v][1];
|
out[z++] = pal[v][1];
|
||||||
out[z++] = pal[v][2];
|
out[z++] = pal[v][2];
|
||||||
@ -4733,14 +4764,14 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
|
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
|
||||||
int z = 0;
|
int z = 0;
|
||||||
int easy=0;
|
int easy=0;
|
||||||
stbi__skip(s, offset - 14 - hsz);
|
stbi__skip(s, info.offset - 14 - info.hsz);
|
||||||
if (bpp == 24) width = 3 * s->img_x;
|
if (info.bpp == 24) width = 3 * s->img_x;
|
||||||
else if (bpp == 16) width = 2*s->img_x;
|
else if (info.bpp == 16) width = 2*s->img_x;
|
||||||
else /* bpp = 32 and pad = 0 */ width=0;
|
else /* bpp = 32 and pad = 0 */ width=0;
|
||||||
pad = (-width) & 3;
|
pad = (-width) & 3;
|
||||||
if (bpp == 24) {
|
if (info.bpp == 24) {
|
||||||
easy = 1;
|
easy = 1;
|
||||||
} else if (bpp == 32) {
|
} else if (info.bpp == 32) {
|
||||||
if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
|
if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
|
||||||
easy = 2;
|
easy = 2;
|
||||||
}
|
}
|
||||||
@ -4765,6 +4796,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
if (target == 4) out[z++] = a;
|
if (target == 4) out[z++] = a;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
int bpp = info.bpp;
|
||||||
for (i=0; i < (int) s->img_x; ++i) {
|
for (i=0; i < (int) s->img_x; ++i) {
|
||||||
stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
|
stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
|
||||||
int a;
|
int a;
|
||||||
@ -4811,20 +4843,55 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// Targa Truevision - TGA
|
// Targa Truevision - TGA
|
||||||
// by Jonathan Dummer
|
// by Jonathan Dummer
|
||||||
#ifndef STBI_NO_TGA
|
#ifndef STBI_NO_TGA
|
||||||
|
// returns STBI_rgb or whatever, 0 on error
|
||||||
|
static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
|
||||||
|
{
|
||||||
|
// only RGB or RGBA (incl. 16bit) or grey allowed
|
||||||
|
if(is_rgb16) *is_rgb16 = 0;
|
||||||
|
switch(bits_per_pixel) {
|
||||||
|
case 8: return STBI_grey;
|
||||||
|
case 16: if(is_grey) return STBI_grey_alpha;
|
||||||
|
// else: fall-through
|
||||||
|
case 15: if(is_rgb16) *is_rgb16 = 1;
|
||||||
|
return STBI_rgb;
|
||||||
|
case 24: // fall-through
|
||||||
|
case 32: return bits_per_pixel/8;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
||||||
{
|
{
|
||||||
int tga_w, tga_h, tga_comp;
|
int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
|
||||||
int sz;
|
int sz, tga_colormap_type;
|
||||||
stbi__get8(s); // discard Offset
|
stbi__get8(s); // discard Offset
|
||||||
sz = stbi__get8(s); // color type
|
tga_colormap_type = stbi__get8(s); // colormap type
|
||||||
if( sz > 1 ) {
|
if( tga_colormap_type > 1 ) {
|
||||||
stbi__rewind(s);
|
stbi__rewind(s);
|
||||||
return 0; // only RGB or indexed allowed
|
return 0; // only RGB or indexed allowed
|
||||||
}
|
}
|
||||||
sz = stbi__get8(s); // image type
|
tga_image_type = stbi__get8(s); // image type
|
||||||
// only RGB or grey allowed, +/- RLE
|
if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
|
||||||
if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0;
|
if (tga_image_type != 1 && tga_image_type != 9) {
|
||||||
stbi__skip(s,9);
|
stbi__rewind(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
stbi__skip(s,4); // skip index of first colormap entry and number of entries
|
||||||
|
sz = stbi__get8(s); // check bits per palette color entry
|
||||||
|
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
|
||||||
|
stbi__rewind(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
stbi__skip(s,4); // skip image x and y origin
|
||||||
|
tga_colormap_bpp = sz;
|
||||||
|
} else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
|
||||||
|
if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
|
||||||
|
stbi__rewind(s);
|
||||||
|
return 0; // only RGB or grey allowed, +/- RLE
|
||||||
|
}
|
||||||
|
stbi__skip(s,9); // skip colormap specification and image x/y origin
|
||||||
|
tga_colormap_bpp = 0;
|
||||||
|
}
|
||||||
tga_w = stbi__get16le(s);
|
tga_w = stbi__get16le(s);
|
||||||
if( tga_w < 1 ) {
|
if( tga_w < 1 ) {
|
||||||
stbi__rewind(s);
|
stbi__rewind(s);
|
||||||
@ -4835,44 +4902,80 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
|||||||
stbi__rewind(s);
|
stbi__rewind(s);
|
||||||
return 0; // test height
|
return 0; // test height
|
||||||
}
|
}
|
||||||
sz = stbi__get8(s); // bits per pixel
|
tga_bits_per_pixel = stbi__get8(s); // bits per pixel
|
||||||
// only RGB or RGBA or grey allowed
|
stbi__get8(s); // ignore alpha bits
|
||||||
if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) {
|
if (tga_colormap_bpp != 0) {
|
||||||
stbi__rewind(s);
|
if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
|
||||||
return 0;
|
// when using a colormap, tga_bits_per_pixel is the size of the indexes
|
||||||
|
// I don't think anything but 8 or 16bit indexes makes sense
|
||||||
|
stbi__rewind(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
|
||||||
|
} else {
|
||||||
|
tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
|
||||||
|
}
|
||||||
|
if(!tga_comp) {
|
||||||
|
stbi__rewind(s);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
tga_comp = sz;
|
|
||||||
if (x) *x = tga_w;
|
if (x) *x = tga_w;
|
||||||
if (y) *y = tga_h;
|
if (y) *y = tga_h;
|
||||||
if (comp) *comp = tga_comp / 8;
|
if (comp) *comp = tga_comp;
|
||||||
return 1; // seems to have passed everything
|
return 1; // seems to have passed everything
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stbi__tga_test(stbi__context *s)
|
static int stbi__tga_test(stbi__context *s)
|
||||||
{
|
{
|
||||||
int res;
|
int res = 0;
|
||||||
int sz;
|
int sz, tga_color_type;
|
||||||
stbi__get8(s); // discard Offset
|
stbi__get8(s); // discard Offset
|
||||||
sz = stbi__get8(s); // color type
|
tga_color_type = stbi__get8(s); // color type
|
||||||
if ( sz > 1 ) return 0; // only RGB or indexed allowed
|
if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed
|
||||||
sz = stbi__get8(s); // image type
|
sz = stbi__get8(s); // image type
|
||||||
if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE
|
if ( tga_color_type == 1 ) { // colormapped (paletted) image
|
||||||
stbi__get16be(s); // discard palette start
|
if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
|
||||||
stbi__get16be(s); // discard palette length
|
stbi__skip(s,4); // skip index of first colormap entry and number of entries
|
||||||
stbi__get8(s); // discard bits per palette color entry
|
sz = stbi__get8(s); // check bits per palette color entry
|
||||||
stbi__get16be(s); // discard x origin
|
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
|
||||||
stbi__get16be(s); // discard y origin
|
stbi__skip(s,4); // skip image x and y origin
|
||||||
if ( stbi__get16be(s) < 1 ) return 0; // test width
|
} else { // "normal" image w/o colormap
|
||||||
if ( stbi__get16be(s) < 1 ) return 0; // test height
|
if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
|
||||||
|
stbi__skip(s,9); // skip colormap specification and image x/y origin
|
||||||
|
}
|
||||||
|
if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width
|
||||||
|
if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height
|
||||||
sz = stbi__get8(s); // bits per pixel
|
sz = stbi__get8(s); // bits per pixel
|
||||||
if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) )
|
if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
|
||||||
res = 0;
|
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
|
||||||
else
|
|
||||||
res = 1;
|
res = 1; // if we got this far, everything's good and we can return 1 instead of 0
|
||||||
|
|
||||||
|
errorEnd:
|
||||||
stbi__rewind(s);
|
stbi__rewind(s);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read 16bit value and convert to 24bit RGB
|
||||||
|
void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
|
||||||
|
{
|
||||||
|
stbi__uint16 px = stbi__get16le(s);
|
||||||
|
stbi__uint16 fiveBitMask = 31;
|
||||||
|
// we have 3 channels with 5bits each
|
||||||
|
int r = (px >> 10) & fiveBitMask;
|
||||||
|
int g = (px >> 5) & fiveBitMask;
|
||||||
|
int b = px & fiveBitMask;
|
||||||
|
// Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
|
||||||
|
out[0] = (r * 255)/31;
|
||||||
|
out[1] = (g * 255)/31;
|
||||||
|
out[2] = (b * 255)/31;
|
||||||
|
|
||||||
|
// some people claim that the most significant bit might be used for alpha
|
||||||
|
// (possibly if an alpha-bit is set in the "image descriptor byte")
|
||||||
|
// but that only made 16bit test images completely translucent..
|
||||||
|
// so let's treat all 15 and 16bit TGAs as RGB with no alpha.
|
||||||
|
}
|
||||||
|
|
||||||
static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
||||||
{
|
{
|
||||||
// read in the TGA header stuff
|
// read in the TGA header stuff
|
||||||
@ -4888,8 +4991,9 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
int tga_width = stbi__get16le(s);
|
int tga_width = stbi__get16le(s);
|
||||||
int tga_height = stbi__get16le(s);
|
int tga_height = stbi__get16le(s);
|
||||||
int tga_bits_per_pixel = stbi__get8(s);
|
int tga_bits_per_pixel = stbi__get8(s);
|
||||||
int tga_comp = tga_bits_per_pixel / 8;
|
int tga_comp, tga_rgb16=0;
|
||||||
int tga_inverted = stbi__get8(s);
|
int tga_inverted = stbi__get8(s);
|
||||||
|
// int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
|
||||||
// image data
|
// image data
|
||||||
unsigned char *tga_data;
|
unsigned char *tga_data;
|
||||||
unsigned char *tga_palette = NULL;
|
unsigned char *tga_palette = NULL;
|
||||||
@ -4905,25 +5009,14 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
tga_image_type -= 8;
|
tga_image_type -= 8;
|
||||||
tga_is_RLE = 1;
|
tga_is_RLE = 1;
|
||||||
}
|
}
|
||||||
/* int tga_alpha_bits = tga_inverted & 15; */
|
|
||||||
tga_inverted = 1 - ((tga_inverted >> 5) & 1);
|
tga_inverted = 1 - ((tga_inverted >> 5) & 1);
|
||||||
|
|
||||||
// error check
|
|
||||||
if ( //(tga_indexed) ||
|
|
||||||
(tga_width < 1) || (tga_height < 1) ||
|
|
||||||
(tga_image_type < 1) || (tga_image_type > 3) ||
|
|
||||||
((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) &&
|
|
||||||
(tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA
|
|
||||||
}
|
|
||||||
|
|
||||||
// If I'm paletted, then I'll use the number of bits from the palette
|
// If I'm paletted, then I'll use the number of bits from the palette
|
||||||
if ( tga_indexed )
|
if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
|
||||||
{
|
else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
|
||||||
tga_comp = tga_palette_bits / 8;
|
|
||||||
}
|
if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
|
||||||
|
return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
|
||||||
|
|
||||||
// tga info
|
// tga info
|
||||||
*x = tga_width;
|
*x = tga_width;
|
||||||
@ -4936,7 +5029,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// skip to the data's starting position (offset usually = 0)
|
// skip to the data's starting position (offset usually = 0)
|
||||||
stbi__skip(s, tga_offset );
|
stbi__skip(s, tga_offset );
|
||||||
|
|
||||||
if ( !tga_indexed && !tga_is_RLE) {
|
if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
|
||||||
for (i=0; i < tga_height; ++i) {
|
for (i=0; i < tga_height; ++i) {
|
||||||
int row = tga_inverted ? tga_height -i - 1 : i;
|
int row = tga_inverted ? tga_height -i - 1 : i;
|
||||||
stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
|
stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
|
||||||
@ -4949,15 +5042,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// any data to skip? (offset usually = 0)
|
// any data to skip? (offset usually = 0)
|
||||||
stbi__skip(s, tga_palette_start );
|
stbi__skip(s, tga_palette_start );
|
||||||
// load the palette
|
// load the palette
|
||||||
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 );
|
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp );
|
||||||
if (!tga_palette) {
|
if (!tga_palette) {
|
||||||
STBI_FREE(tga_data);
|
STBI_FREE(tga_data);
|
||||||
return stbi__errpuc("outofmem", "Out of memory");
|
return stbi__errpuc("outofmem", "Out of memory");
|
||||||
}
|
}
|
||||||
if (!stbi__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) {
|
if (tga_rgb16) {
|
||||||
STBI_FREE(tga_data);
|
stbi_uc *pal_entry = tga_palette;
|
||||||
STBI_FREE(tga_palette);
|
STBI_ASSERT(tga_comp == STBI_rgb);
|
||||||
return stbi__errpuc("bad palette", "Corrupt TGA");
|
for (i=0; i < tga_palette_len; ++i) {
|
||||||
|
stbi__tga_read_rgb16(s, pal_entry);
|
||||||
|
pal_entry += tga_comp;
|
||||||
|
}
|
||||||
|
} else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
|
||||||
|
STBI_FREE(tga_data);
|
||||||
|
STBI_FREE(tga_palette);
|
||||||
|
return stbi__errpuc("bad palette", "Corrupt TGA");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// load the data
|
// load the data
|
||||||
@ -4987,23 +5087,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// load however much data we did have
|
// load however much data we did have
|
||||||
if ( tga_indexed )
|
if ( tga_indexed )
|
||||||
{
|
{
|
||||||
// read in 1 byte, then perform the lookup
|
// read in index, then perform the lookup
|
||||||
int pal_idx = stbi__get8(s);
|
int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
|
||||||
if ( pal_idx >= tga_palette_len )
|
if ( pal_idx >= tga_palette_len ) {
|
||||||
{
|
// invalid index
|
||||||
// invalid index
|
|
||||||
pal_idx = 0;
|
pal_idx = 0;
|
||||||
}
|
}
|
||||||
pal_idx *= tga_bits_per_pixel / 8;
|
pal_idx *= tga_comp;
|
||||||
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
for (j = 0; j < tga_comp; ++j) {
|
||||||
{
|
|
||||||
raw_data[j] = tga_palette[pal_idx+j];
|
raw_data[j] = tga_palette[pal_idx+j];
|
||||||
}
|
}
|
||||||
} else
|
} else if(tga_rgb16) {
|
||||||
{
|
STBI_ASSERT(tga_comp == STBI_rgb);
|
||||||
|
stbi__tga_read_rgb16(s, raw_data);
|
||||||
|
} else {
|
||||||
// read in the data raw
|
// read in the data raw
|
||||||
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
for (j = 0; j < tga_comp; ++j) {
|
||||||
{
|
|
||||||
raw_data[j] = stbi__get8(s);
|
raw_data[j] = stbi__get8(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5042,8 +5141,8 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// swap RGB
|
// swap RGB - if the source data was RGB16, it already is in the right order
|
||||||
if (tga_comp >= 3)
|
if (tga_comp >= 3 && !tga_rgb16)
|
||||||
{
|
{
|
||||||
unsigned char* tga_pixel = tga_data;
|
unsigned char* tga_pixel = tga_data;
|
||||||
for (i=0; i < tga_width * tga_height; ++i)
|
for (i=0; i < tga_width * tga_height; ++i)
|
||||||
@ -6017,7 +6116,7 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
|
|||||||
char *token;
|
char *token;
|
||||||
int valid = 0;
|
int valid = 0;
|
||||||
|
|
||||||
if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) {
|
if (stbi__hdr_test(s) == 0) {
|
||||||
stbi__rewind( s );
|
stbi__rewind( s );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -6054,29 +6153,17 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
|
|||||||
#ifndef STBI_NO_BMP
|
#ifndef STBI_NO_BMP
|
||||||
static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
|
static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
|
||||||
{
|
{
|
||||||
int hsz;
|
void *p;
|
||||||
if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') {
|
stbi__bmp_data info;
|
||||||
stbi__rewind( s );
|
|
||||||
return 0;
|
info.all_a = 255;
|
||||||
}
|
p = stbi__bmp_parse_header(s, &info);
|
||||||
stbi__skip(s,12);
|
stbi__rewind( s );
|
||||||
hsz = stbi__get32le(s);
|
if (p == NULL)
|
||||||
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) {
|
return 0;
|
||||||
stbi__rewind( s );
|
*x = s->img_x;
|
||||||
return 0;
|
*y = s->img_y;
|
||||||
}
|
*comp = info.ma ? 4 : 3;
|
||||||
if (hsz == 12) {
|
|
||||||
*x = stbi__get16le(s);
|
|
||||||
*y = stbi__get16le(s);
|
|
||||||
} else {
|
|
||||||
*x = stbi__get32le(s);
|
|
||||||
*y = stbi__get32le(s);
|
|
||||||
}
|
|
||||||
if (stbi__get16le(s) != 1) {
|
|
||||||
stbi__rewind( s );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*comp = stbi__get16le(s) / 8;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -6222,8 +6309,16 @@ static int stbi__pnm_isspace(char c)
|
|||||||
|
|
||||||
static void stbi__pnm_skip_whitespace(stbi__context *s, char *c)
|
static void stbi__pnm_skip_whitespace(stbi__context *s, char *c)
|
||||||
{
|
{
|
||||||
while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
|
for (;;) {
|
||||||
*c = (char) stbi__get8(s);
|
while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
|
||||||
|
*c = (char) stbi__get8(s);
|
||||||
|
|
||||||
|
if (stbi__at_eof(s) || *c != '#')
|
||||||
|
break;
|
||||||
|
|
||||||
|
while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
|
||||||
|
*c = (char) stbi__get8(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stbi__pnm_isdigit(char c)
|
static int stbi__pnm_isdigit(char c)
|
||||||
@ -6361,10 +6456,16 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
revision history:
|
revision history:
|
||||||
|
2.09 (2016-01-16) allow comments in PNM files
|
||||||
|
16-bit-per-pixel TGA (not bit-per-component)
|
||||||
|
info() for TGA could break due to .hdr handling
|
||||||
|
info() for BMP to shares code instead of sloppy parse
|
||||||
|
can use STBI_REALLOC_SIZED if allocator doesn't support realloc
|
||||||
|
code cleanup
|
||||||
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) fix compiler warnings
|
2.07 (2015-09-13) fix compiler warnings
|
||||||
partial animated GIF support
|
partial animated GIF support
|
||||||
limited 16-bit PSD support
|
limited 16-bpc PSD support
|
||||||
#ifdef unused functions
|
#ifdef unused functions
|
||||||
bug with < 92 byte PIC,PNM,HDR,TGA
|
bug with < 92 byte PIC,PNM,HDR,TGA
|
||||||
2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
|
2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* stb_image_write - v1.00 - public domain - http://nothings.org/stb/stb_image_write.h
|
/* stb_image_write - v1.01 - 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
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ USAGE:
|
|||||||
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
||||||
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||||
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||||
int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
|
int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
|
||||||
|
|
||||||
There are also four equivalent functions that use an arbitrary write function. You are
|
There are also four equivalent functions that use an arbitrary write function. You are
|
||||||
expected to open/close your file-equivalent before and after calling these:
|
expected to open/close your file-equivalent before and after calling these:
|
||||||
@ -98,12 +98,16 @@ CREDITS:
|
|||||||
github:Chribba
|
github:Chribba
|
||||||
Guillaume Chereau
|
Guillaume Chereau
|
||||||
github:jry2
|
github:jry2
|
||||||
|
github:romigrou
|
||||||
|
Sergio Gonzalez
|
||||||
|
Jonas Karlsson
|
||||||
|
Filip Wasil
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
|
|
||||||
This software is in the public domain. Where that dedication is not
|
This software is in the public domain. Where that dedication is not
|
||||||
recognized, you are granted a perpetual, irrevocable license to copy,
|
recognized, you are granted a perpetual, irrevocable license to copy,
|
||||||
distribute, and modify this file as you see fit.
|
distribute, and modify this file as you see fit.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -144,8 +148,12 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w,
|
|||||||
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
|
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
#ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||||
#define _CRT_NONSTDC_NO_DEPRECATE
|
#define _CRT_NONSTDC_NO_DEPRECATE
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STBI_WRITE_NO_STDIO
|
#ifndef STBI_WRITE_NO_STDIO
|
||||||
@ -157,19 +165,25 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
|
#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
|
||||||
// ok
|
// ok
|
||||||
#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
|
#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
|
||||||
// ok
|
// ok
|
||||||
#else
|
#else
|
||||||
#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
|
#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STBIW_MALLOC
|
#ifndef STBIW_MALLOC
|
||||||
#define STBIW_MALLOC(sz) malloc(sz)
|
#define STBIW_MALLOC(sz) malloc(sz)
|
||||||
#define STBIW_REALLOC(p,sz) realloc(p,sz)
|
#define STBIW_REALLOC(p,newsz) realloc(p,newsz)
|
||||||
#define STBIW_FREE(p) free(p)
|
#define STBIW_FREE(p) free(p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef STBIW_REALLOC_SIZED
|
||||||
|
#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef STBIW_MEMMOVE
|
#ifndef STBIW_MEMMOVE
|
||||||
#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
|
#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
|
||||||
#endif
|
#endif
|
||||||
@ -180,6 +194,8 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w,
|
|||||||
#define STBIW_ASSERT(x) assert(x)
|
#define STBIW_ASSERT(x) assert(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
stbi_write_func *func;
|
stbi_write_func *func;
|
||||||
@ -228,21 +244,21 @@ static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
|
|||||||
while (*fmt) {
|
while (*fmt) {
|
||||||
switch (*fmt++) {
|
switch (*fmt++) {
|
||||||
case ' ': break;
|
case ' ': break;
|
||||||
case '1': { unsigned char x = (unsigned char) va_arg(v, int);
|
case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
|
||||||
s->func(s->context,&x,1);
|
s->func(s->context,&x,1);
|
||||||
break; }
|
break; }
|
||||||
case '2': { int x = va_arg(v,int);
|
case '2': { int x = va_arg(v,int);
|
||||||
unsigned char b[2];
|
unsigned char b[2];
|
||||||
b[0] = (unsigned char) x;
|
b[0] = STBIW_UCHAR(x);
|
||||||
b[1] = (unsigned char) (x>>8);
|
b[1] = STBIW_UCHAR(x>>8);
|
||||||
s->func(s->context,b,2);
|
s->func(s->context,b,2);
|
||||||
break; }
|
break; }
|
||||||
case '4': { stbiw_uint32 x = va_arg(v,int);
|
case '4': { stbiw_uint32 x = va_arg(v,int);
|
||||||
unsigned char b[4];
|
unsigned char b[4];
|
||||||
b[0]=(unsigned char)x;
|
b[0]=STBIW_UCHAR(x);
|
||||||
b[1]=(unsigned char)(x>>8);
|
b[1]=STBIW_UCHAR(x>>8);
|
||||||
b[2]=(unsigned char)(x>>16);
|
b[2]=STBIW_UCHAR(x>>16);
|
||||||
b[3]=(unsigned char)(x>>24);
|
b[3]=STBIW_UCHAR(x>>24);
|
||||||
s->func(s->context,b,4);
|
s->func(s->context,b,4);
|
||||||
break; }
|
break; }
|
||||||
default:
|
default:
|
||||||
@ -419,13 +435,13 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (diff) {
|
if (diff) {
|
||||||
unsigned char header = (unsigned char) (len - 1);
|
unsigned char header = STBIW_UCHAR(len - 1);
|
||||||
s->func(s->context, &header, 1);
|
s->func(s->context, &header, 1);
|
||||||
for (k = 0; k < len; ++k) {
|
for (k = 0; k < len; ++k) {
|
||||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
|
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned char header = (unsigned char) (len - 129);
|
unsigned char header = STBIW_UCHAR(len - 129);
|
||||||
s->func(s->context, &header, 1);
|
s->func(s->context, &header, 1);
|
||||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
|
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
|
||||||
}
|
}
|
||||||
@ -467,7 +483,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
|
|||||||
int exponent;
|
int exponent;
|
||||||
float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
|
float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
|
||||||
|
|
||||||
if (maxcomp < 1e-32) {
|
if (maxcomp < 1e-32f) {
|
||||||
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
|
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
|
||||||
} else {
|
} else {
|
||||||
float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
|
float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
|
||||||
@ -481,7 +497,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
|
|||||||
|
|
||||||
void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
|
void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
|
||||||
{
|
{
|
||||||
unsigned char lengthbyte = (unsigned char) (length+128);
|
unsigned char lengthbyte = STBIW_UCHAR(length+128);
|
||||||
STBIW_ASSERT(length+128 <= 255);
|
STBIW_ASSERT(length+128 <= 255);
|
||||||
s->func(s->context, &lengthbyte, 1);
|
s->func(s->context, &lengthbyte, 1);
|
||||||
s->func(s->context, &databyte, 1);
|
s->func(s->context, &databyte, 1);
|
||||||
@ -489,7 +505,7 @@ void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char dat
|
|||||||
|
|
||||||
void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
|
void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
|
||||||
{
|
{
|
||||||
unsigned char lengthbyte = (unsigned char )(length & 0xff);
|
unsigned char lengthbyte = STBIW_UCHAR(length);
|
||||||
STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
|
STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
|
||||||
s->func(s->context, &lengthbyte, 1);
|
s->func(s->context, &lengthbyte, 1);
|
||||||
s->func(s->context, data, length);
|
s->func(s->context, data, length);
|
||||||
@ -647,7 +663,7 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da
|
|||||||
static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
|
static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
|
||||||
{
|
{
|
||||||
int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
|
int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
|
||||||
void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
|
void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
|
||||||
STBIW_ASSERT(p);
|
STBIW_ASSERT(p);
|
||||||
if (p) {
|
if (p) {
|
||||||
if (!*arr) ((int *) p)[1] = 0;
|
if (!*arr) ((int *) p)[1] = 0;
|
||||||
@ -660,7 +676,7 @@ static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
|
|||||||
static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
|
static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
|
||||||
{
|
{
|
||||||
while (*bitcount >= 8) {
|
while (*bitcount >= 8) {
|
||||||
stbiw__sbpush(data, (unsigned char) *bitbuffer);
|
stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
|
||||||
*bitbuffer >>= 8;
|
*bitbuffer >>= 8;
|
||||||
*bitcount -= 8;
|
*bitcount -= 8;
|
||||||
}
|
}
|
||||||
@ -795,7 +811,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
|
|||||||
|
|
||||||
{
|
{
|
||||||
// compute adler32 on input
|
// compute adler32 on input
|
||||||
unsigned int k=0, s1=1, s2=0;
|
unsigned int s1=1, s2=0;
|
||||||
int blocklen = (int) (data_len % 5552);
|
int blocklen = (int) (data_len % 5552);
|
||||||
j=0;
|
j=0;
|
||||||
while (j < data_len) {
|
while (j < data_len) {
|
||||||
@ -804,10 +820,10 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
|
|||||||
j += blocklen;
|
j += blocklen;
|
||||||
blocklen = 5552;
|
blocklen = 5552;
|
||||||
}
|
}
|
||||||
stbiw__sbpush(out, (unsigned char) (s2 >> 8));
|
stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
|
||||||
stbiw__sbpush(out, (unsigned char) s2);
|
stbiw__sbpush(out, STBIW_UCHAR(s2));
|
||||||
stbiw__sbpush(out, (unsigned char) (s1 >> 8));
|
stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
|
||||||
stbiw__sbpush(out, (unsigned char) s1);
|
stbiw__sbpush(out, STBIW_UCHAR(s1));
|
||||||
}
|
}
|
||||||
*out_len = stbiw__sbn(out);
|
*out_len = stbiw__sbn(out);
|
||||||
// make returned pointer freeable
|
// make returned pointer freeable
|
||||||
@ -815,21 +831,52 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
|
|||||||
return (unsigned char *) stbiw__sbraw(out);
|
return (unsigned char *) stbiw__sbraw(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int stbiw__crc32(unsigned char *buffer, int len)
|
static unsigned int stbiw__crc32(unsigned char *buffer, int len)
|
||||||
{
|
{
|
||||||
static unsigned int crc_table[256];
|
static unsigned int crc_table[256] =
|
||||||
|
{
|
||||||
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
|
0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||||
|
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||||
|
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||||
|
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||||
|
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||||
|
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||||
|
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||||
|
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||||
|
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||||
|
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||||
|
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||||
|
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||||
|
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||||
|
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||||
|
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||||
|
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||||
|
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||||
|
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||||
|
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||||
|
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||||
|
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||||
|
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||||
|
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||||
|
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||||
|
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||||
|
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||||
|
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||||
|
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||||
|
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||||
|
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||||
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||||
|
};
|
||||||
|
|
||||||
unsigned int crc = ~0u;
|
unsigned int crc = ~0u;
|
||||||
int i,j;
|
int i;
|
||||||
if (crc_table[1] == 0)
|
|
||||||
for(i=0; i < 256; i++)
|
|
||||||
for (crc_table[i]=i, j=0; j < 8; ++j)
|
|
||||||
crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
|
|
||||||
for (i=0; i < len; ++i)
|
for (i=0; i < len; ++i)
|
||||||
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
|
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
|
||||||
return ~crc;
|
return ~crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
|
#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
|
||||||
#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
|
#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
|
||||||
#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
|
#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
|
||||||
|
|
||||||
@ -842,9 +889,9 @@ static void stbiw__wpcrc(unsigned char **data, int len)
|
|||||||
static unsigned char stbiw__paeth(int a, int b, int c)
|
static unsigned char stbiw__paeth(int a, int b, int c)
|
||||||
{
|
{
|
||||||
int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
|
int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
|
||||||
if (pa <= pb && pa <= pc) return (unsigned char) a;
|
if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
|
||||||
if (pb <= pc) return (unsigned char) b;
|
if (pb <= pc) return STBIW_UCHAR(b);
|
||||||
return (unsigned char) c;
|
return STBIW_UCHAR(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
|
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
|
||||||
@ -917,7 +964,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
|
|||||||
stbiw__wp32(o, x);
|
stbiw__wp32(o, x);
|
||||||
stbiw__wp32(o, y);
|
stbiw__wp32(o, y);
|
||||||
*o++ = 8;
|
*o++ = 8;
|
||||||
*o++ = (unsigned char) ctype[n];
|
*o++ = STBIW_UCHAR(ctype[n]);
|
||||||
*o++ = 0;
|
*o++ = 0;
|
||||||
*o++ = 0;
|
*o++ = 0;
|
||||||
*o++ = 0;
|
*o++ = 0;
|
||||||
@ -968,6 +1015,10 @@ 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.01 (2016-01-16)
|
||||||
|
STBIW_REALLOC_SIZED: support allocators with no realloc support
|
||||||
|
avoid race-condition in crc initialization
|
||||||
|
minor compile issues
|
||||||
1.00 (2015-09-14)
|
1.00 (2015-09-14)
|
||||||
installable file IO function
|
installable file IO function
|
||||||
0.99 (2015-09-13)
|
0.99 (2015-09-13)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// stb_truetype.h - v1.08 - public domain
|
// stb_truetype.h - v1.09 - 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:
|
||||||
@ -42,12 +42,15 @@
|
|||||||
// Sergey Popov
|
// Sergey Popov
|
||||||
// Giumo X. Clanjor
|
// Giumo X. Clanjor
|
||||||
// Higor Euripedes
|
// Higor Euripedes
|
||||||
|
// Thomas Fields
|
||||||
|
// Derek Vinyard
|
||||||
//
|
//
|
||||||
// Misc other:
|
// Misc other:
|
||||||
// Ryan Gordon
|
// Ryan Gordon
|
||||||
//
|
//
|
||||||
// VERSION HISTORY
|
// VERSION HISTORY
|
||||||
//
|
//
|
||||||
|
// 1.09 (????-??-??) warning fix; avoid crash on outofmem
|
||||||
// 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;
|
||||||
// variant PackFontRanges to pack and render in separate phases;
|
// variant PackFontRanges to pack and render in separate phases;
|
||||||
@ -1556,7 +1559,7 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
|||||||
|
|
||||||
STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
|
STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
|
||||||
{
|
{
|
||||||
int x0,y0,x1,y1;
|
int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
|
||||||
if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
|
if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
|
||||||
// e.g. space character
|
// e.g. space character
|
||||||
if (ix0) *ix0 = 0;
|
if (ix0) *ix0 = 0;
|
||||||
@ -1672,6 +1675,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
|
|||||||
{
|
{
|
||||||
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
|
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
|
||||||
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
||||||
|
STBTT_assert(z != NULL);
|
||||||
if (!z) return z;
|
if (!z) return z;
|
||||||
|
|
||||||
// round dx down to avoid overshooting
|
// round dx down to avoid overshooting
|
||||||
@ -1693,6 +1697,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
|
|||||||
{
|
{
|
||||||
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
|
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
|
||||||
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
||||||
|
STBTT_assert(z != NULL);
|
||||||
//STBTT_assert(e->y0 <= start_point);
|
//STBTT_assert(e->y0 <= start_point);
|
||||||
if (!z) return z;
|
if (!z) return z;
|
||||||
z->fdx = dxdy;
|
z->fdx = dxdy;
|
||||||
@ -1817,21 +1822,23 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
|||||||
while (e->y0 <= scan_y) {
|
while (e->y0 <= scan_y) {
|
||||||
if (e->y1 > scan_y) {
|
if (e->y1 > scan_y) {
|
||||||
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
|
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
|
||||||
// find insertion point
|
if (z != NULL) {
|
||||||
if (active == NULL)
|
// find insertion point
|
||||||
active = z;
|
if (active == NULL)
|
||||||
else if (z->x < active->x) {
|
active = z;
|
||||||
// insert at front
|
else if (z->x < active->x) {
|
||||||
z->next = active;
|
// insert at front
|
||||||
active = z;
|
z->next = active;
|
||||||
} else {
|
active = z;
|
||||||
// find thing to insert AFTER
|
} else {
|
||||||
stbtt__active_edge *p = active;
|
// find thing to insert AFTER
|
||||||
while (p->next && p->next->x < z->x)
|
stbtt__active_edge *p = active;
|
||||||
p = p->next;
|
while (p->next && p->next->x < z->x)
|
||||||
// at this point, p->next->x is NOT < z->x
|
p = p->next;
|
||||||
z->next = p->next;
|
// at this point, p->next->x is NOT < z->x
|
||||||
p->next = z;
|
z->next = p->next;
|
||||||
|
p->next = z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++e;
|
++e;
|
||||||
@ -2101,10 +2108,12 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
|||||||
while (e->y0 <= scan_y_bottom) {
|
while (e->y0 <= scan_y_bottom) {
|
||||||
if (e->y0 != e->y1) {
|
if (e->y0 != e->y1) {
|
||||||
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
|
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
|
||||||
STBTT_assert(z->ey >= scan_y_top);
|
if (z != NULL) {
|
||||||
// insert at front
|
STBTT_assert(z->ey >= scan_y_top);
|
||||||
z->next = active;
|
// insert at front
|
||||||
active = z;
|
z->next = active;
|
||||||
|
active = z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++e;
|
++e;
|
||||||
}
|
}
|
||||||
@ -2706,6 +2715,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i
|
|||||||
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
|
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
|
||||||
int safe_w = w - kernel_width;
|
int safe_w = w - kernel_width;
|
||||||
int j;
|
int j;
|
||||||
|
STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
|
||||||
for (j=0; j < h; ++j) {
|
for (j=0; j < h; ++j) {
|
||||||
int i;
|
int i;
|
||||||
unsigned int total;
|
unsigned int total;
|
||||||
@ -2767,6 +2777,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i
|
|||||||
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
|
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
|
||||||
int safe_h = h - kernel_width;
|
int safe_h = h - kernel_width;
|
||||||
int j;
|
int j;
|
||||||
|
STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
|
||||||
for (j=0; j < w; ++j) {
|
for (j=0; j < w; ++j) {
|
||||||
int i;
|
int i;
|
||||||
unsigned int total;
|
unsigned int total;
|
||||||
|
297
stb_vorbis.c
297
stb_vorbis.c
@ -1,8 +1,11 @@
|
|||||||
// Ogg Vorbis audio decoder - v1.06 - public domain
|
// Ogg Vorbis audio decoder - v1.07 - public domain
|
||||||
// http://nothings.org/stb_vorbis/
|
// http://nothings.org/stb_vorbis/
|
||||||
//
|
//
|
||||||
// Written by Sean Barrett in 2007, last updated in 2014
|
// Original version written by Sean Barrett in 2007.
|
||||||
// Sponsored by RAD Game Tools.
|
//
|
||||||
|
// Originally sponsored by RAD Game Tools. Seeking sponsored
|
||||||
|
// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software,
|
||||||
|
// Aras Pranckevicius, and Sean Barrett.
|
||||||
//
|
//
|
||||||
// LICENSE
|
// LICENSE
|
||||||
//
|
//
|
||||||
@ -30,11 +33,10 @@
|
|||||||
// 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
|
||||||
// (If you reported a bug but do not appear in this list, it is because
|
// Phillip Bennefall Rohit
|
||||||
// someone else reported the bug before you. There were too many of you to
|
|
||||||
// list them all because I was lax about updating for a long time, sorry.)
|
|
||||||
//
|
//
|
||||||
// Partial history:
|
// Partial history:
|
||||||
|
// 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
|
||||||
// fix some inappropriately signed shifts
|
// fix some inappropriately signed shifts
|
||||||
@ -45,8 +47,6 @@
|
|||||||
// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
|
// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
|
||||||
// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
|
// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
|
||||||
// (API change) report sample rate for decode-full-file funcs
|
// (API change) report sample rate for decode-full-file funcs
|
||||||
// 0.99996 - - bracket #include <malloc.h> for macintosh compilation
|
|
||||||
// 0.99995 - - avoid alias-optimization issue in float-to-int conversion
|
|
||||||
//
|
//
|
||||||
// See end of file for full version history.
|
// See end of file for full version history.
|
||||||
|
|
||||||
@ -155,10 +155,10 @@ extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
|
|||||||
// specification does not bound the size of an individual frame.
|
// specification does not bound the size of an individual frame.
|
||||||
|
|
||||||
extern stb_vorbis *stb_vorbis_open_pushdata(
|
extern stb_vorbis *stb_vorbis_open_pushdata(
|
||||||
unsigned char *datablock, int datablock_length_in_bytes,
|
const unsigned char * datablock, int datablock_length_in_bytes,
|
||||||
int *datablock_memory_consumed_in_bytes,
|
int *datablock_memory_consumed_in_bytes,
|
||||||
int *error,
|
int *error,
|
||||||
stb_vorbis_alloc *alloc_buffer);
|
const stb_vorbis_alloc *alloc_buffer);
|
||||||
// create a vorbis decoder by passing in the initial data block containing
|
// create a vorbis decoder by passing in the initial data block containing
|
||||||
// the ogg&vorbis headers (you don't need to do parse them, just provide
|
// the ogg&vorbis headers (you don't need to do parse them, just provide
|
||||||
// the first N bytes of the file--you're told if it's not enough, see below)
|
// the first N bytes of the file--you're told if it's not enough, see below)
|
||||||
@ -169,7 +169,8 @@ extern stb_vorbis *stb_vorbis_open_pushdata(
|
|||||||
// incomplete and you need to pass in a larger block from the start of the file
|
// incomplete and you need to pass in a larger block from the start of the file
|
||||||
|
|
||||||
extern int stb_vorbis_decode_frame_pushdata(
|
extern int stb_vorbis_decode_frame_pushdata(
|
||||||
stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes,
|
stb_vorbis *f,
|
||||||
|
const unsigned char *datablock, int datablock_length_in_bytes,
|
||||||
int *channels, // place to write number of float * buffers
|
int *channels, // place to write number of float * buffers
|
||||||
float ***output, // place to write float ** array of float * buffers
|
float ***output, // place to write float ** array of float * buffers
|
||||||
int *samples // place to write number of output samples
|
int *samples // place to write number of output samples
|
||||||
@ -233,18 +234,18 @@ extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *chan
|
|||||||
// When you're done with it, just free() the pointer returned in *output.
|
// When you're done with it, just free() the pointer returned in *output.
|
||||||
|
|
||||||
extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
|
extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
|
||||||
int *error, stb_vorbis_alloc *alloc_buffer);
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
|
// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
|
||||||
// this must be the entire stream!). on failure, returns NULL and sets *error
|
// this must be the entire stream!). on failure, returns NULL and sets *error
|
||||||
|
|
||||||
#ifndef STB_VORBIS_NO_STDIO
|
#ifndef STB_VORBIS_NO_STDIO
|
||||||
extern stb_vorbis * stb_vorbis_open_filename(const char *filename,
|
extern stb_vorbis * stb_vorbis_open_filename(const char *filename,
|
||||||
int *error, stb_vorbis_alloc *alloc_buffer);
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
// create an ogg vorbis decoder from a filename via fopen(). on failure,
|
// create an ogg vorbis decoder from a filename via fopen(). on failure,
|
||||||
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
|
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
|
||||||
|
|
||||||
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
|
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
|
||||||
int *error, stb_vorbis_alloc *alloc_buffer);
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||||
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
|
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
|
||||||
// note that stb_vorbis must "own" this stream; if you seek it in between
|
// note that stb_vorbis must "own" this stream; if you seek it in between
|
||||||
@ -254,7 +255,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
|
|||||||
// function, stb_vorbis_open_file_section(), to limit it.
|
// function, stb_vorbis_open_file_section(), to limit it.
|
||||||
|
|
||||||
extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
|
extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
|
||||||
int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len);
|
int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len);
|
||||||
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||||
// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
|
// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
|
||||||
// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
|
// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
|
||||||
@ -292,15 +293,17 @@ extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***out
|
|||||||
extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
|
extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
|
||||||
extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);
|
extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);
|
||||||
#endif
|
#endif
|
||||||
// decode the next frame and return the number of samples per channel. the
|
// decode the next frame and return the number of *samples* per channel.
|
||||||
// data is coerced to the number of channels you request according to the
|
// Note that for interleaved data, you pass in the number of shorts (the
|
||||||
|
// size of your array), but the return value is the number of samples per
|
||||||
|
// channel, not the total number of samples.
|
||||||
|
//
|
||||||
|
// The data is coerced to the number of channels you request according to the
|
||||||
// channel coercion rules (see below). You must pass in the size of your
|
// channel coercion rules (see below). You must pass in the size of your
|
||||||
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
|
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
|
||||||
// The maximum buffer size needed can be gotten from get_info(); however,
|
// The maximum buffer size needed can be gotten from get_info(); however,
|
||||||
// the Vorbis I specification implies an absolute maximum of 4096 samples
|
// the Vorbis I specification implies an absolute maximum of 4096 samples
|
||||||
// per channel. Note that for interleaved data, you pass in the number of
|
// per channel.
|
||||||
// shorts (the size of your array), but the return value is the number of
|
|
||||||
// samples per channel, not the total number of samples.
|
|
||||||
|
|
||||||
// Channel coercion rules:
|
// Channel coercion rules:
|
||||||
// Let M be the number of channels requested, and N the number of channels present,
|
// Let M be the number of channels requested, and N the number of channels present,
|
||||||
@ -367,7 +370,7 @@ enum STBVorbisError
|
|||||||
VORBIS_invalid_first_page,
|
VORBIS_invalid_first_page,
|
||||||
VORBIS_bad_packet_type,
|
VORBIS_bad_packet_type,
|
||||||
VORBIS_cant_find_last_page,
|
VORBIS_cant_find_last_page,
|
||||||
VORBIS_seek_failed,
|
VORBIS_seek_failed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -488,14 +491,8 @@ enum STBVorbisError
|
|||||||
// trade off storage for speed.
|
// trade off storage for speed.
|
||||||
//#define STB_VORBIS_DIVIDES_IN_CODEBOOK
|
//#define STB_VORBIS_DIVIDES_IN_CODEBOOK
|
||||||
|
|
||||||
// STB_VORBIS_CODEBOOK_SHORTS
|
#ifdef STB_VORBIS_CODEBOOK_SHORTS
|
||||||
// The vorbis file format encodes VQ codebook floats as ax+b where a and
|
#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats"
|
||||||
// b are floating point per-codebook constants, and x is a 16-bit int.
|
|
||||||
// Normally, stb_vorbis decodes them to floats rather than leaving them
|
|
||||||
// as 16-bit ints and computing ax+b while decoding. This is a speed/space
|
|
||||||
// tradeoff; you can save space by defining this flag.
|
|
||||||
#ifndef STB_VORBIS_CODEBOOK_SHORTS
|
|
||||||
#define STB_VORBIS_CODEBOOK_FLOATS
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// STB_VORBIS_DIVIDE_TABLE
|
// STB_VORBIS_DIVIDE_TABLE
|
||||||
@ -556,11 +553,26 @@ enum STBVorbisError
|
|||||||
#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh))
|
#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh))
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else // STB_VORBIS_NO_CRT
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
#endif
|
#define malloc(s) 0
|
||||||
|
#define free(s) ((void) 0)
|
||||||
|
#define realloc(s) 0
|
||||||
|
#endif // STB_VORBIS_NO_CRT
|
||||||
|
|
||||||
#if !defined(_MSC_VER) && !(defined(__MINGW32__) && defined(__forceinline))
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
// eff you mingw:
|
||||||
|
// "fixed":
|
||||||
|
// http://sourceforge.net/p/mingw-w64/mailman/message/32882927/
|
||||||
|
// "no that broke the build, reverted, who cares about C":
|
||||||
|
// http://sourceforge.net/p/mingw-w64/mailman/message/32890381/
|
||||||
|
#ifdef __forceinline
|
||||||
|
#undef __forceinline
|
||||||
|
#endif
|
||||||
|
#define __forceinline
|
||||||
|
#elif !defined(_MSC_VER)
|
||||||
#if __GNUC__
|
#if __GNUC__
|
||||||
#define __forceinline inline
|
#define __forceinline inline
|
||||||
#else
|
#else
|
||||||
@ -577,6 +589,13 @@ enum STBVorbisError
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1])
|
||||||
|
#else
|
||||||
|
#define CHECK(f) ((void) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_BLOCKSIZE_LOG 13 // from specification
|
#define MAX_BLOCKSIZE_LOG 13 // from specification
|
||||||
#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG)
|
#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG)
|
||||||
|
|
||||||
@ -593,11 +612,7 @@ typedef signed int int32;
|
|||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef STB_VORBIS_CODEBOOK_FLOATS
|
|
||||||
typedef float codetype;
|
typedef float codetype;
|
||||||
#else
|
|
||||||
typedef uint16 codetype;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// @NOTE
|
// @NOTE
|
||||||
//
|
//
|
||||||
@ -831,13 +846,6 @@ struct stb_vorbis
|
|||||||
int channel_buffer_end;
|
int channel_buffer_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int my_prof(int slot);
|
|
||||||
//#define stb_prof my_prof
|
|
||||||
|
|
||||||
#ifndef stb_prof
|
|
||||||
#define stb_prof(x) ((void) 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(STB_VORBIS_NO_PUSHDATA_API)
|
#if defined(STB_VORBIS_NO_PUSHDATA_API)
|
||||||
#define IS_PUSH_MODE(f) FALSE
|
#define IS_PUSH_MODE(f) FALSE
|
||||||
#elif defined(STB_VORBIS_NO_PULLDATA_API)
|
#elif defined(STB_VORBIS_NO_PULLDATA_API)
|
||||||
@ -904,7 +912,7 @@ static void *setup_malloc(vorb *f, int sz)
|
|||||||
|
|
||||||
static void setup_free(vorb *f, void *p)
|
static void setup_free(vorb *f, void *p)
|
||||||
{
|
{
|
||||||
if (f->alloc.alloc_buffer) return; // do nothing; setup mem is not a stack
|
if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,10 +1063,12 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
|
|||||||
while (z > 0 && !available[z]) --z;
|
while (z > 0 && !available[z]) --z;
|
||||||
if (z == 0) { return FALSE; }
|
if (z == 0) { return FALSE; }
|
||||||
res = available[z];
|
res = available[z];
|
||||||
|
assert(z >= 0 && z < 32);
|
||||||
available[z] = 0;
|
available[z] = 0;
|
||||||
add_entry(c, bit_reverse(res), i, m++, len[i], values);
|
add_entry(c, bit_reverse(res), i, m++, len[i], values);
|
||||||
// propogate availability up the tree
|
// propogate availability up the tree
|
||||||
if (z != len[i]) {
|
if (z != len[i]) {
|
||||||
|
assert(len[i] >= 0 && len[i] < 32);
|
||||||
for (y=len[i]; y > z; --y) {
|
for (y=len[i]; y > z; --y) {
|
||||||
assert(available[y] == 0);
|
assert(available[y] == 0);
|
||||||
available[y] = res + (1 << (32-y));
|
available[y] = res + (1 << (32-y));
|
||||||
@ -1576,7 +1586,7 @@ enum
|
|||||||
{
|
{
|
||||||
VORBIS_packet_id = 1,
|
VORBIS_packet_id = 1,
|
||||||
VORBIS_packet_comment = 3,
|
VORBIS_packet_comment = 3,
|
||||||
VORBIS_packet_setup = 5,
|
VORBIS_packet_setup = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
static int codebook_decode_scalar_raw(vorb *f, Codebook *c)
|
static int codebook_decode_scalar_raw(vorb *f, Codebook *c)
|
||||||
@ -1584,7 +1594,9 @@ static int codebook_decode_scalar_raw(vorb *f, Codebook *c)
|
|||||||
int i;
|
int i;
|
||||||
prep_huffman(f);
|
prep_huffman(f);
|
||||||
|
|
||||||
assert(c->sorted_codewords || c->codewords);
|
if (c->codewords == NULL && c->sorted_codewords == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
// cases to use binary search: sorted_codewords && !c->codewords
|
// cases to use binary search: sorted_codewords && !c->codewords
|
||||||
// sorted_codewords && c->entries > 8
|
// sorted_codewords && c->entries > 8
|
||||||
if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) {
|
if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) {
|
||||||
@ -1692,15 +1704,9 @@ static int codebook_decode_scalar(vorb *f, Codebook *c)
|
|||||||
|
|
||||||
// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case
|
// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case
|
||||||
// where we avoid one addition
|
// where we avoid one addition
|
||||||
#ifndef STB_VORBIS_CODEBOOK_FLOATS
|
#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off])
|
||||||
#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value)
|
#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off])
|
||||||
#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value)
|
#define CODEBOOK_ELEMENT_BASE(c) (0)
|
||||||
#define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value)
|
|
||||||
#else
|
|
||||||
#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off])
|
|
||||||
#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off])
|
|
||||||
#define CODEBOOK_ELEMENT_BASE(c) (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int codebook_decode_start(vorb *f, Codebook *c)
|
static int codebook_decode_start(vorb *f, Codebook *c)
|
||||||
{
|
{
|
||||||
@ -1892,7 +1898,6 @@ static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **o
|
|||||||
|
|
||||||
{
|
{
|
||||||
z *= c->dimensions;
|
z *= c->dimensions;
|
||||||
stb_prof(11);
|
|
||||||
if (c->sequence_p) {
|
if (c->sequence_p) {
|
||||||
// haven't optimized this case because I don't have any examples
|
// haven't optimized this case because I don't have any examples
|
||||||
for (i=0; i < effective; ++i) {
|
for (i=0; i < effective; ++i) {
|
||||||
@ -1904,7 +1909,7 @@ static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **o
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i=0;
|
i=0;
|
||||||
if (c_inter == 1) {
|
if (c_inter == 1 && i < effective) {
|
||||||
float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
|
float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;
|
||||||
if (outputs[c_inter])
|
if (outputs[c_inter])
|
||||||
outputs[c_inter][p_inter] += val;
|
outputs[c_inter][p_inter] += val;
|
||||||
@ -2076,15 +2081,17 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
|
|||||||
#endif
|
#endif
|
||||||
ady -= abs(base) * adx;
|
ady -= abs(base) * adx;
|
||||||
if (x1 > n) x1 = n;
|
if (x1 > n) x1 = n;
|
||||||
LINE_OP(output[x], inverse_db_table[y]);
|
if (x < x1) {
|
||||||
for (++x; x < x1; ++x) {
|
|
||||||
err += ady;
|
|
||||||
if (err >= adx) {
|
|
||||||
err -= adx;
|
|
||||||
y += sy;
|
|
||||||
} else
|
|
||||||
y += base;
|
|
||||||
LINE_OP(output[x], inverse_db_table[y]);
|
LINE_OP(output[x], inverse_db_table[y]);
|
||||||
|
for (++x; x < x1; ++x) {
|
||||||
|
err += ady;
|
||||||
|
if (err >= adx) {
|
||||||
|
err -= adx;
|
||||||
|
y += sy;
|
||||||
|
} else
|
||||||
|
y += base;
|
||||||
|
LINE_OP(output[x], inverse_db_table[y]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2123,7 +2130,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications));
|
int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stb_prof(2);
|
CHECK(f);
|
||||||
|
|
||||||
for (i=0; i < ch; ++i)
|
for (i=0; i < ch; ++i)
|
||||||
if (!do_not_decode[i])
|
if (!do_not_decode[i])
|
||||||
memset(residue_buffers[i], 0, sizeof(float) * n);
|
memset(residue_buffers[i], 0, sizeof(float) * n);
|
||||||
@ -2135,11 +2143,9 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
if (j == ch)
|
if (j == ch)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
stb_prof(3);
|
|
||||||
for (pass=0; pass < 8; ++pass) {
|
for (pass=0; pass < 8; ++pass) {
|
||||||
int pcount = 0, class_set = 0;
|
int pcount = 0, class_set = 0;
|
||||||
if (ch == 2) {
|
if (ch == 2) {
|
||||||
stb_prof(13);
|
|
||||||
while (pcount < part_read) {
|
while (pcount < part_read) {
|
||||||
int z = r->begin + pcount*r->part_size;
|
int z = r->begin + pcount*r->part_size;
|
||||||
int c_inter = (z & 1), p_inter = z>>1;
|
int c_inter = (z & 1), p_inter = z>>1;
|
||||||
@ -2157,7 +2163,6 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
stb_prof(5);
|
|
||||||
for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
|
for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
|
||||||
int z = r->begin + pcount*r->part_size;
|
int z = r->begin + pcount*r->part_size;
|
||||||
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
|
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
|
||||||
@ -2168,23 +2173,20 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
int b = r->residue_books[c][pass];
|
int b = r->residue_books[c][pass];
|
||||||
if (b >= 0) {
|
if (b >= 0) {
|
||||||
Codebook *book = f->codebooks + b;
|
Codebook *book = f->codebooks + b;
|
||||||
stb_prof(20); // accounts for X time
|
|
||||||
#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
|
#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
|
||||||
if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
|
if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
|
||||||
goto done;
|
goto done;
|
||||||
#else
|
#else
|
||||||
// saves 1%
|
// saves 1%
|
||||||
if (!codebook_decode_deinterleave_repeat_2(f, book, residue_buffers, &c_inter, &p_inter, n, r->part_size))
|
if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
|
||||||
goto done;
|
goto done;
|
||||||
#endif
|
#endif
|
||||||
stb_prof(7);
|
|
||||||
} else {
|
} else {
|
||||||
z += r->part_size;
|
z += r->part_size;
|
||||||
c_inter = z & 1;
|
c_inter = z & 1;
|
||||||
p_inter = z >> 1;
|
p_inter = z >> 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stb_prof(8);
|
|
||||||
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
|
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
|
||||||
++class_set;
|
++class_set;
|
||||||
#endif
|
#endif
|
||||||
@ -2217,10 +2219,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
int b = r->residue_books[c][pass];
|
int b = r->residue_books[c][pass];
|
||||||
if (b >= 0) {
|
if (b >= 0) {
|
||||||
Codebook *book = f->codebooks + b;
|
Codebook *book = f->codebooks + b;
|
||||||
stb_prof(22);
|
|
||||||
if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
|
if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
|
||||||
goto done;
|
goto done;
|
||||||
stb_prof(3);
|
|
||||||
} else {
|
} else {
|
||||||
z += r->part_size;
|
z += r->part_size;
|
||||||
c_inter = 0;
|
c_inter = 0;
|
||||||
@ -2259,10 +2259,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
int b = r->residue_books[c][pass];
|
int b = r->residue_books[c][pass];
|
||||||
if (b >= 0) {
|
if (b >= 0) {
|
||||||
Codebook *book = f->codebooks + b;
|
Codebook *book = f->codebooks + b;
|
||||||
stb_prof(22);
|
|
||||||
if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
|
if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
|
||||||
goto done;
|
goto done;
|
||||||
stb_prof(3);
|
|
||||||
} else {
|
} else {
|
||||||
z += r->part_size;
|
z += r->part_size;
|
||||||
c_inter = z % ch;
|
c_inter = z % ch;
|
||||||
@ -2277,7 +2275,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
stb_prof(9);
|
CHECK(f);
|
||||||
|
|
||||||
for (pass=0; pass < 8; ++pass) {
|
for (pass=0; pass < 8; ++pass) {
|
||||||
int pcount = 0, class_set=0;
|
int pcount = 0, class_set=0;
|
||||||
@ -2326,7 +2324,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
stb_prof(0);
|
CHECK(f);
|
||||||
temp_alloc_restore(f,temp_alloc_point);
|
temp_alloc_restore(f,temp_alloc_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3140,13 +3138,16 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f
|
|||||||
int hx = g->Xlist[j];
|
int hx = g->Xlist[j];
|
||||||
if (lx != hx)
|
if (lx != hx)
|
||||||
draw_line(target, lx,ly, hx,hy, n2);
|
draw_line(target, lx,ly, hx,hy, n2);
|
||||||
|
CHECK(f);
|
||||||
lx = hx, ly = hy;
|
lx = hx, ly = hy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lx < n2)
|
if (lx < n2) {
|
||||||
// optimization of: draw_line(target, lx,ly, n,ly, n2);
|
// optimization of: draw_line(target, lx,ly, n,ly, n2);
|
||||||
for (j=lx; j < n2; ++j)
|
for (j=lx; j < n2; ++j)
|
||||||
LINE_OP(target[j], inverse_db_table[ly]);
|
LINE_OP(target[j], inverse_db_table[ly]);
|
||||||
|
CHECK(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -3217,6 +3218,7 @@ static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, in
|
|||||||
*p_right_start = window_center;
|
*p_right_start = window_center;
|
||||||
*p_right_end = n;
|
*p_right_end = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3235,7 +3237,8 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
// FLOORS
|
// FLOORS
|
||||||
n2 = n >> 1;
|
n2 = n >> 1;
|
||||||
|
|
||||||
stb_prof(1);
|
CHECK(f);
|
||||||
|
|
||||||
for (i=0; i < f->channels; ++i) {
|
for (i=0; i < f->channels; ++i) {
|
||||||
int s = map->chan[i].mux, floor;
|
int s = map->chan[i].mux, floor;
|
||||||
zero_channel[i] = FALSE;
|
zero_channel[i] = FALSE;
|
||||||
@ -3327,7 +3330,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
// at this point we've decoded the floor into buffer
|
// at this point we've decoded the floor into buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stb_prof(0);
|
CHECK(f);
|
||||||
// at this point we've decoded all floors
|
// at this point we've decoded all floors
|
||||||
|
|
||||||
if (f->alloc.alloc_buffer)
|
if (f->alloc.alloc_buffer)
|
||||||
@ -3340,6 +3343,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE;
|
zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHECK(f);
|
||||||
// RESIDUE DECODE
|
// RESIDUE DECODE
|
||||||
for (i=0; i < map->submaps; ++i) {
|
for (i=0; i < map->submaps; ++i) {
|
||||||
float *residue_buffers[STB_VORBIS_MAX_CHANNELS];
|
float *residue_buffers[STB_VORBIS_MAX_CHANNELS];
|
||||||
@ -3364,9 +3368,9 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
|
|
||||||
if (f->alloc.alloc_buffer)
|
if (f->alloc.alloc_buffer)
|
||||||
assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
|
assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
|
||||||
|
CHECK(f);
|
||||||
|
|
||||||
// INVERSE COUPLING
|
// INVERSE COUPLING
|
||||||
stb_prof(14);
|
|
||||||
for (i = map->coupling_steps-1; i >= 0; --i) {
|
for (i = map->coupling_steps-1; i >= 0; --i) {
|
||||||
int n2 = n >> 1;
|
int n2 = n >> 1;
|
||||||
float *m = f->channel_buffers[map->chan[i].magnitude];
|
float *m = f->channel_buffers[map->chan[i].magnitude];
|
||||||
@ -3387,10 +3391,10 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
a[j] = a2;
|
a[j] = a2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CHECK(f);
|
||||||
|
|
||||||
// finish decoding the floors
|
// finish decoding the floors
|
||||||
#ifndef STB_VORBIS_NO_DEFER_FLOOR
|
#ifndef STB_VORBIS_NO_DEFER_FLOOR
|
||||||
stb_prof(15);
|
|
||||||
for (i=0; i < f->channels; ++i) {
|
for (i=0; i < f->channels; ++i) {
|
||||||
if (really_zero_channel[i]) {
|
if (really_zero_channel[i]) {
|
||||||
memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);
|
memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);
|
||||||
@ -3410,10 +3414,10 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// INVERSE MDCT
|
// INVERSE MDCT
|
||||||
stb_prof(16);
|
CHECK(f);
|
||||||
for (i=0; i < f->channels; ++i)
|
for (i=0; i < f->channels; ++i)
|
||||||
inverse_mdct(f->channel_buffers[i], n, f, m->blockflag);
|
inverse_mdct(f->channel_buffers[i], n, f, m->blockflag);
|
||||||
stb_prof(0);
|
CHECK(f);
|
||||||
|
|
||||||
// this shouldn't be necessary, unless we exited on an error
|
// this shouldn't be necessary, unless we exited on an error
|
||||||
// and want to flush to get to the next packet
|
// and want to flush to get to the next packet
|
||||||
@ -3455,7 +3459,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) {
|
if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) {
|
||||||
uint32 current_end = f->known_loc_for_packet - (n-right_end);
|
uint32 current_end = f->known_loc_for_packet - (n-right_end);
|
||||||
// then let's infer the size of the (probably) short final frame
|
// then let's infer the size of the (probably) short final frame
|
||||||
if (current_end < f->current_loc + right_end) {
|
if (current_end < f->current_loc + (right_end-left_start)) {
|
||||||
if (current_end < f->current_loc) {
|
if (current_end < f->current_loc) {
|
||||||
// negative truncation, that's impossible!
|
// negative truncation, that's impossible!
|
||||||
*len = 0;
|
*len = 0;
|
||||||
@ -3463,6 +3467,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
*len = current_end - f->current_loc;
|
*len = current_end - f->current_loc;
|
||||||
}
|
}
|
||||||
*len += left_start;
|
*len += left_start;
|
||||||
|
if (*len > right_end) *len = right_end; // this should never happen
|
||||||
f->current_loc += *len;
|
f->current_loc += *len;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -3480,6 +3485,8 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|||||||
if (f->alloc.alloc_buffer)
|
if (f->alloc.alloc_buffer)
|
||||||
assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
|
assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
|
||||||
*len = right_end; // ignore samples after the window goes to 0
|
*len = right_end; // ignore samples after the window goes to 0
|
||||||
|
CHECK(f);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3645,14 +3652,15 @@ static int start_decoder(vorb *f)
|
|||||||
get32(f); // bitrate_nominal
|
get32(f); // bitrate_nominal
|
||||||
get32(f); // bitrate_minimum
|
get32(f); // bitrate_minimum
|
||||||
x = get8(f);
|
x = get8(f);
|
||||||
{ int log0,log1;
|
{
|
||||||
log0 = x & 15;
|
int log0,log1;
|
||||||
log1 = x >> 4;
|
log0 = x & 15;
|
||||||
f->blocksize_0 = 1 << log0;
|
log1 = x >> 4;
|
||||||
f->blocksize_1 = 1 << log1;
|
f->blocksize_0 = 1 << log0;
|
||||||
if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup);
|
f->blocksize_1 = 1 << log1;
|
||||||
if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup);
|
if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup);
|
||||||
if (log0 > log1) return error(f, VORBIS_invalid_setup);
|
if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup);
|
||||||
|
if (log0 > log1) return error(f, VORBIS_invalid_setup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// framing_flag
|
// framing_flag
|
||||||
@ -3701,6 +3709,7 @@ static int start_decoder(vorb *f)
|
|||||||
int total=0;
|
int total=0;
|
||||||
uint8 *lengths;
|
uint8 *lengths;
|
||||||
Codebook *c = f->codebooks+i;
|
Codebook *c = f->codebooks+i;
|
||||||
|
CHECK(f);
|
||||||
x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup);
|
x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup);
|
||||||
x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup);
|
x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup);
|
||||||
x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup);
|
x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup);
|
||||||
@ -3712,6 +3721,8 @@ static int start_decoder(vorb *f)
|
|||||||
ordered = get_bits(f,1);
|
ordered = get_bits(f,1);
|
||||||
c->sparse = ordered ? 0 : get_bits(f,1);
|
c->sparse = ordered ? 0 : get_bits(f,1);
|
||||||
|
|
||||||
|
if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup);
|
||||||
|
|
||||||
if (c->sparse)
|
if (c->sparse)
|
||||||
lengths = (uint8 *) setup_temp_malloc(f, c->entries);
|
lengths = (uint8 *) setup_temp_malloc(f, c->entries);
|
||||||
else
|
else
|
||||||
@ -3736,6 +3747,8 @@ static int start_decoder(vorb *f)
|
|||||||
if (present) {
|
if (present) {
|
||||||
lengths[j] = get_bits(f, 5) + 1;
|
lengths[j] = get_bits(f, 5) + 1;
|
||||||
++total;
|
++total;
|
||||||
|
if (lengths[j] == 32)
|
||||||
|
return error(f, VORBIS_invalid_setup);
|
||||||
} else {
|
} else {
|
||||||
lengths[j] = NO_CODE;
|
lengths[j] = NO_CODE;
|
||||||
}
|
}
|
||||||
@ -3770,6 +3783,7 @@ static int start_decoder(vorb *f)
|
|||||||
c->sorted_entries = sorted_count;
|
c->sorted_entries = sorted_count;
|
||||||
values = NULL;
|
values = NULL;
|
||||||
|
|
||||||
|
CHECK(f);
|
||||||
if (!c->sparse) {
|
if (!c->sparse) {
|
||||||
c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries);
|
c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries);
|
||||||
if (!c->codewords) return error(f, VORBIS_outofmem);
|
if (!c->codewords) return error(f, VORBIS_outofmem);
|
||||||
@ -3815,6 +3829,7 @@ static int start_decoder(vorb *f)
|
|||||||
|
|
||||||
compute_accelerated_huffman(c);
|
compute_accelerated_huffman(c);
|
||||||
|
|
||||||
|
CHECK(f);
|
||||||
c->lookup_type = get_bits(f, 4);
|
c->lookup_type = get_bits(f, 4);
|
||||||
if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup);
|
if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup);
|
||||||
if (c->lookup_type > 0) {
|
if (c->lookup_type > 0) {
|
||||||
@ -3828,6 +3843,7 @@ static int start_decoder(vorb *f)
|
|||||||
} else {
|
} else {
|
||||||
c->lookup_values = c->entries * c->dimensions;
|
c->lookup_values = c->entries * c->dimensions;
|
||||||
}
|
}
|
||||||
|
if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup);
|
||||||
mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);
|
mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);
|
||||||
if (mults == NULL) return error(f, VORBIS_outofmem);
|
if (mults == NULL) return error(f, VORBIS_outofmem);
|
||||||
for (j=0; j < (int) c->lookup_values; ++j) {
|
for (j=0; j < (int) c->lookup_values; ++j) {
|
||||||
@ -3839,6 +3855,7 @@ static int start_decoder(vorb *f)
|
|||||||
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
|
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
|
||||||
if (c->lookup_type == 1) {
|
if (c->lookup_type == 1) {
|
||||||
int len, sparse = c->sparse;
|
int len, sparse = c->sparse;
|
||||||
|
float last=0;
|
||||||
// pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop
|
// pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop
|
||||||
if (sparse) {
|
if (sparse) {
|
||||||
if (c->sorted_entries == 0) goto skip;
|
if (c->sorted_entries == 0) goto skip;
|
||||||
@ -3848,21 +3865,22 @@ static int start_decoder(vorb *f)
|
|||||||
if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
|
if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
|
||||||
len = sparse ? c->sorted_entries : c->entries;
|
len = sparse ? c->sorted_entries : c->entries;
|
||||||
for (j=0; j < len; ++j) {
|
for (j=0; j < len; ++j) {
|
||||||
int z = sparse ? c->sorted_values[j] : j, div=1;
|
unsigned int z = sparse ? c->sorted_values[j] : j;
|
||||||
|
unsigned int div=1;
|
||||||
for (k=0; k < c->dimensions; ++k) {
|
for (k=0; k < c->dimensions; ++k) {
|
||||||
int off = (z / div) % c->lookup_values;
|
int off = (z / div) % c->lookup_values;
|
||||||
c->multiplicands[j*c->dimensions + k] =
|
float val = mults[off];
|
||||||
#ifndef STB_VORBIS_CODEBOOK_FLOATS
|
val = mults[off]*c->delta_value + c->minimum_value + last;
|
||||||
mults[off];
|
c->multiplicands[j*c->dimensions + k] = val;
|
||||||
#else
|
if (c->sequence_p)
|
||||||
mults[off]*c->delta_value + c->minimum_value;
|
last = val;
|
||||||
// in this case (and this case only) we could pre-expand c->sequence_p,
|
if (k+1 < c->dimensions) {
|
||||||
// and throw away the decode logic for it; have to ALSO do
|
if (div > UINT_MAX / (unsigned int) c->lookup_values) {
|
||||||
// it in the case below, but it can only be done if
|
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
|
||||||
// STB_VORBIS_CODEBOOK_FLOATS
|
return error(f, VORBIS_invalid_setup);
|
||||||
// !STB_VORBIS_DIVIDES_IN_CODEBOOK
|
}
|
||||||
#endif
|
div *= c->lookup_values;
|
||||||
div *= c->lookup_values;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
|
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
|
||||||
@ -3871,28 +3889,25 @@ static int start_decoder(vorb *f)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
float last=0;
|
||||||
|
CHECK(f);
|
||||||
c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);
|
c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);
|
||||||
if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
|
if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
|
||||||
#ifndef STB_VORBIS_CODEBOOK_FLOATS
|
for (j=0; j < (int) c->lookup_values; ++j) {
|
||||||
memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values);
|
float val = mults[j] * c->delta_value + c->minimum_value + last;
|
||||||
#else
|
c->multiplicands[j] = val;
|
||||||
for (j=0; j < (int) c->lookup_values; ++j)
|
if (c->sequence_p)
|
||||||
c->multiplicands[j] = mults[j] * c->delta_value + c->minimum_value;
|
last = val;
|
||||||
#endif
|
}
|
||||||
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
|
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
|
||||||
|
|
||||||
#ifdef STB_VORBIS_CODEBOOK_FLOATS
|
CHECK(f);
|
||||||
if (c->lookup_type == 2 && c->sequence_p) {
|
|
||||||
for (j=1; j < (int) c->lookup_values; ++j)
|
|
||||||
c->multiplicands[j] = c->multiplicands[j-1];
|
|
||||||
c->sequence_p = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
CHECK(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// time domain transfers (notused)
|
// time domain transfers (notused)
|
||||||
@ -3988,9 +4003,11 @@ static int start_decoder(vorb *f)
|
|||||||
if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup);
|
if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup);
|
||||||
r->begin = get_bits(f, 24);
|
r->begin = get_bits(f, 24);
|
||||||
r->end = get_bits(f, 24);
|
r->end = get_bits(f, 24);
|
||||||
|
if (r->end < r->begin) return error(f, VORBIS_invalid_setup);
|
||||||
r->part_size = get_bits(f,24)+1;
|
r->part_size = get_bits(f,24)+1;
|
||||||
r->classifications = get_bits(f,6)+1;
|
r->classifications = get_bits(f,6)+1;
|
||||||
r->classbook = get_bits(f,8);
|
r->classbook = get_bits(f,8);
|
||||||
|
if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup);
|
||||||
for (j=0; j < r->classifications; ++j) {
|
for (j=0; j < r->classifications; ++j) {
|
||||||
uint8 high_bits=0;
|
uint8 high_bits=0;
|
||||||
uint8 low_bits=get_bits(f,3);
|
uint8 low_bits=get_bits(f,3);
|
||||||
@ -4171,6 +4188,7 @@ static void vorbis_deinit(stb_vorbis *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p->codebooks) {
|
if (p->codebooks) {
|
||||||
|
CHECK(p);
|
||||||
for (i=0; i < p->codebook_count; ++i) {
|
for (i=0; i < p->codebook_count; ++i) {
|
||||||
Codebook *c = p->codebooks + i;
|
Codebook *c = p->codebooks + i;
|
||||||
setup_free(p, c->codeword_lengths);
|
setup_free(p, c->codeword_lengths);
|
||||||
@ -4189,6 +4207,7 @@ static void vorbis_deinit(stb_vorbis *p)
|
|||||||
setup_free(p, p->mapping[i].chan);
|
setup_free(p, p->mapping[i].chan);
|
||||||
setup_free(p, p->mapping);
|
setup_free(p, p->mapping);
|
||||||
}
|
}
|
||||||
|
CHECK(p);
|
||||||
for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) {
|
for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) {
|
||||||
setup_free(p, p->channel_buffers[i]);
|
setup_free(p, p->channel_buffers[i]);
|
||||||
setup_free(p, p->previous_window[i]);
|
setup_free(p, p->previous_window[i]);
|
||||||
@ -4216,7 +4235,7 @@ void stb_vorbis_close(stb_vorbis *p)
|
|||||||
setup_free(p,p);
|
setup_free(p,p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vorbis_init(stb_vorbis *p, stb_vorbis_alloc *z)
|
static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z)
|
||||||
{
|
{
|
||||||
memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start
|
memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start
|
||||||
if (z) {
|
if (z) {
|
||||||
@ -4374,11 +4393,11 @@ static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len)
|
|||||||
|
|
||||||
// return value: number of bytes we used
|
// return value: number of bytes we used
|
||||||
int stb_vorbis_decode_frame_pushdata(
|
int stb_vorbis_decode_frame_pushdata(
|
||||||
stb_vorbis *f, // the file we're decoding
|
stb_vorbis *f, // the file we're decoding
|
||||||
uint8 *data, int data_len, // the memory available for decoding
|
const uint8 *data, int data_len, // the memory available for decoding
|
||||||
int *channels, // place to write number of float * buffers
|
int *channels, // place to write number of float * buffers
|
||||||
float ***output, // place to write float ** array of float * buffers
|
float ***output, // place to write float ** array of float * buffers
|
||||||
int *samples // place to write number of output samples
|
int *samples // place to write number of output samples
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -4388,11 +4407,11 @@ int stb_vorbis_decode_frame_pushdata(
|
|||||||
|
|
||||||
if (f->page_crc_tests >= 0) {
|
if (f->page_crc_tests >= 0) {
|
||||||
*samples = 0;
|
*samples = 0;
|
||||||
return vorbis_search_for_page_pushdata(f, data, data_len);
|
return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
f->stream = data;
|
f->stream = (uint8 *) data;
|
||||||
f->stream_end = data + data_len;
|
f->stream_end = (uint8 *) data + data_len;
|
||||||
f->error = VORBIS__no_error;
|
f->error = VORBIS__no_error;
|
||||||
|
|
||||||
// check that we have the entire packet in memory
|
// check that we have the entire packet in memory
|
||||||
@ -4444,14 +4463,14 @@ int stb_vorbis_decode_frame_pushdata(
|
|||||||
}
|
}
|
||||||
|
|
||||||
stb_vorbis *stb_vorbis_open_pushdata(
|
stb_vorbis *stb_vorbis_open_pushdata(
|
||||||
unsigned char *data, int data_len, // the memory available for decoding
|
const unsigned char *data, int data_len, // the memory available for decoding
|
||||||
int *data_used, // only defined if result is not NULL
|
int *data_used, // only defined if result is not NULL
|
||||||
int *error, stb_vorbis_alloc *alloc)
|
int *error, const stb_vorbis_alloc *alloc)
|
||||||
{
|
{
|
||||||
stb_vorbis *f, p;
|
stb_vorbis *f, p;
|
||||||
vorbis_init(&p, alloc);
|
vorbis_init(&p, alloc);
|
||||||
p.stream = data;
|
p.stream = (uint8 *) data;
|
||||||
p.stream_end = data + data_len;
|
p.stream_end = (uint8 *) data + data_len;
|
||||||
p.push_mode = TRUE;
|
p.push_mode = TRUE;
|
||||||
if (!start_decoder(&p)) {
|
if (!start_decoder(&p)) {
|
||||||
if (p.eof)
|
if (p.eof)
|
||||||
@ -4971,7 +4990,7 @@ int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output)
|
|||||||
|
|
||||||
#ifndef STB_VORBIS_NO_STDIO
|
#ifndef STB_VORBIS_NO_STDIO
|
||||||
|
|
||||||
stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc, unsigned int length)
|
stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length)
|
||||||
{
|
{
|
||||||
stb_vorbis *f, p;
|
stb_vorbis *f, p;
|
||||||
vorbis_init(&p, alloc);
|
vorbis_init(&p, alloc);
|
||||||
@ -4992,7 +5011,7 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, 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 = ftell(file);
|
||||||
@ -5002,7 +5021,7 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorbis_alloc *alloc)
|
stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename, "rb");
|
FILE *f = fopen(filename, "rb");
|
||||||
if (f)
|
if (f)
|
||||||
@ -5012,7 +5031,7 @@ stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorb
|
|||||||
}
|
}
|
||||||
#endif // STB_VORBIS_NO_STDIO
|
#endif // STB_VORBIS_NO_STDIO
|
||||||
|
|
||||||
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, stb_vorbis_alloc *alloc)
|
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)
|
||||||
{
|
{
|
||||||
stb_vorbis *f, p;
|
stb_vorbis *f, p;
|
||||||
if (data == NULL) return NULL;
|
if (data == NULL) return NULL;
|
||||||
@ -5392,6 +5411,8 @@ 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.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API
|
||||||
|
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)
|
||||||
some crash fixes when out of memory or with corrupt files
|
some crash fixes when out of memory or with corrupt files
|
||||||
1.05 - 2015/04/19 - don't define __forceinline if it's redundant
|
1.05 - 2015/04/19 - don't define __forceinline if it's redundant
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#define STB_DEFINE
|
#define STB_DEFINE
|
||||||
#include "stb.h"
|
#include "stb.h"
|
||||||
|
|
||||||
#define PNGSUITE_PRIMARY
|
//#define PNGSUITE_PRIMARY
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void test_ycbcr(void)
|
void test_ycbcr(void)
|
||||||
@ -65,7 +65,7 @@ int main(int argc, char **argv)
|
|||||||
int w,h;
|
int w,h;
|
||||||
//test_ycbcr();
|
//test_ycbcr();
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
// test hdr asserts
|
// test hdr asserts
|
||||||
for (h=0; h < 100; h += 2)
|
for (h=0; h < 100; h += 2)
|
||||||
for (w=0; w < 200; ++w)
|
for (w=0; w < 200; ++w)
|
||||||
@ -81,15 +81,17 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
for (i=1; i < argc; ++i) {
|
for (i=1; i < argc; ++i) {
|
||||||
int res;
|
int res;
|
||||||
|
int w2,h2,n2;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
printf("%s\n", argv[i]);
|
printf("%s\n", argv[i]);
|
||||||
res = stbi_info(argv[1], &w, &h, &n);
|
res = stbi_info(argv[1], &w2, &h2, &n2);
|
||||||
data = stbi_load(argv[i], &w, &h, &n, 4); if (data) free(data); else printf("Failed &n\n");
|
data = stbi_load(argv[i], &w, &h, &n, 4); if (data) free(data); else printf("Failed &n\n");
|
||||||
data = stbi_load(argv[i], &w, &h, 0, 1); if (data) free(data); else printf("Failed 1\n");
|
data = stbi_load(argv[i], &w, &h, 0, 1); if (data) free(data); else printf("Failed 1\n");
|
||||||
data = stbi_load(argv[i], &w, &h, 0, 2); if (data) free(data); else printf("Failed 2\n");
|
data = stbi_load(argv[i], &w, &h, 0, 2); if (data) free(data); else printf("Failed 2\n");
|
||||||
data = stbi_load(argv[i], &w, &h, 0, 3); if (data) free(data); else printf("Failed 3\n");
|
data = stbi_load(argv[i], &w, &h, 0, 3); if (data) free(data); else printf("Failed 3\n");
|
||||||
data = stbi_load(argv[i], &w, &h, 0, 4);
|
data = stbi_load(argv[i], &w, &h, &n, 4);
|
||||||
assert(data);
|
assert(data);
|
||||||
|
assert(w == w2 && h == h2 && n == n2);
|
||||||
assert(res);
|
assert(res);
|
||||||
if (data) {
|
if (data) {
|
||||||
char fname[512];
|
char fname[512];
|
||||||
|
@ -130,6 +130,10 @@ SOURCE=..\stb_leakcheck.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\stb_malloc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\stb_perlin.h
|
SOURCE=..\stb_perlin.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -8,10 +8,11 @@ extern void stb_vorbis_dumpmem(void);
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
size_t memlen;
|
size_t memlen;
|
||||||
unsigned char *mem = stb_fileu("c:/x/theme_03.ogg", &memlen);
|
unsigned char *mem = stb_fileu("c:/x/sketch008.ogg", &memlen);
|
||||||
int chan, samplerate;
|
int chan, samplerate;
|
||||||
short *output;
|
short *output;
|
||||||
int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output);
|
int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output);
|
||||||
|
stb_filewrite("c:/x/sketch008.raw", output, samples*4);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user