mirror of https://github.com/nothings/stb.git
Compare commits
23 Commits
fb9f0df93d
...
d703f53193
Author | SHA1 | Date |
---|---|---|
Jeremy English | d703f53193 | |
Sean Barrett | ae721c50ea | |
Jeff Roberts (Bellevue) | 2fb057af65 | |
Jeff Roberts (Bellevue) | 1828f357dc | |
Sean Barrett | b7cf124628 | |
Jeff Roberts (Bellevue) | c59da6729e | |
Jeff Roberts (Bellevue) | 7f7e3469cf | |
Jeff Roberts (Bellevue) | 7a075fe7c7 | |
Sean Barrett | f4a71b1337 | |
Sean Barrett | a8a25e17b5 | |
Sean Barrett | 0bc88af4de | |
Sean Barrett | 0ca75da4ec | |
Sean Barrett | 9d924f8a47 | |
Fabian Giesen | 4da08a1dbd | |
Fabian Giesen | c6d7c32e5d | |
Fabian Giesen | 07268cbf36 | |
Fabian Giesen | ed64333410 | |
Fabian Giesen | 45eb4ac158 | |
Fabian Giesen | e5f0e18d0f | |
Fabian Giesen | d373674115 | |
Sean Barrett | 03f50e343d | |
Sean Barrett | 1d878bd2a3 | |
Jeremy English | 163fa11fb1 |
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
*.obj
|
||||
*.exe
|
12
README.md
12
README.md
|
@ -5,6 +5,8 @@ stb
|
|||
|
||||
single-file public domain (or MIT licensed) libraries for C/C++
|
||||
|
||||
# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries.
|
||||
|
||||
Noteworthy:
|
||||
|
||||
* image loader: [stb_image.h](stb_image.h)
|
||||
|
@ -13,8 +15,8 @@ Noteworthy:
|
|||
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
|
||||
* typesafe containers: [stb_ds.h](stb_ds.h)
|
||||
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts.
|
||||
|
||||
<a name="stb_libs"></a>
|
||||
|
||||
|
@ -22,10 +24,10 @@ library | lastest version | category | LoC | description
|
|||
--------------------- | ---- | -------- | --- | --------------------------------
|
||||
**[stb_vorbis.c](stb_vorbis.c)** | 1.22 | audio | 5584 | decode ogg vorbis files from file/memory to float/16-bit signed output
|
||||
**[stb_hexwave.h](stb_hexwave.h)** | 0.5 | audio | 680 | audio waveform synthesizer
|
||||
**[stb_image.h](stb_image.h)** | 2.28 | graphics | 7987 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
||||
**[stb_image.h](stb_image.h)** | 2.29 | graphics | 7985 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
||||
**[stb_truetype.h](stb_truetype.h)** | 1.26 | graphics | 5077 | parse, decode, and rasterize characters from truetype fonts
|
||||
**[stb_image_write.h](stb_image_write.h)** | 1.16 | graphics | 1724 | image writing to disk: PNG, TGA, BMP
|
||||
**[stb_image_resize2.h](stb_image_resize2.h)** | 2.01 | graphics | 10303 | resize images larger/smaller with good quality
|
||||
**[stb_image_resize2.h](stb_image_resize2.h)** | 2.04 | graphics | 10325 | resize images larger/smaller with good quality
|
||||
**[stb_rect_pack.h](stb_rect_pack.h)** | 1.01 | graphics | 623 | simple 2D rectangle packer with decent quality
|
||||
**[stb_perlin.h](stb_perlin.h)** | 0.5 | graphics | 428 | perlin's revised simplex noise w/ different seeds
|
||||
**[stb_ds.h](stb_ds.h)** | 0.67 | utility | 1895 | typesafe dynamic array and hash tables for C, will compile in C++
|
||||
|
@ -43,7 +45,7 @@ library | lastest version | category | LoC | description
|
|||
**[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL
|
||||
|
||||
Total libraries: 21
|
||||
Total lines of C code: 50786
|
||||
Total lines of C code: 50806
|
||||
|
||||
|
||||
FAQ
|
||||
|
|
|
@ -501,12 +501,12 @@ int stb_c_lexer_get_token(stb_lexer *lexer)
|
|||
// skip whitespace and comments
|
||||
for (;;) {
|
||||
#ifdef STB_C_LEX_ISWHITE
|
||||
while (p != lexer->stream_end) {
|
||||
while (p != lexer->eof) {
|
||||
int n;
|
||||
n = STB_C_LEX_ISWHITE(p);
|
||||
if (n == 0) break;
|
||||
if (lexer->eof && lexer->eof - lexer->parse_point < n)
|
||||
return stb__clex_token(tok, CLEX_parse_error, p,lexer->eof-1);
|
||||
return stb__clex_token(lexer, CLEX_parse_error, p,lexer->eof-1);
|
||||
p += n;
|
||||
}
|
||||
#else
|
||||
|
|
348
stb_image.h
348
stb_image.h
|
@ -1,4 +1,4 @@
|
|||
/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
|
||||
/* stb_image - v2.29 - public domain image loader - http://nothings.org/stb
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Do this:
|
||||
|
@ -48,6 +48,7 @@ LICENSE
|
|||
|
||||
RECENT REVISION HISTORY:
|
||||
|
||||
2.29 (2023-05-xx) optimizations
|
||||
2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
|
||||
2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
|
||||
2.26 (2020-07-13) many minor fixes
|
||||
|
@ -1072,8 +1073,8 @@ static int stbi__addints_valid(int a, int b)
|
|||
return a <= INT_MAX - b;
|
||||
}
|
||||
|
||||
// returns 1 if the product of two signed shorts is valid, 0 on overflow.
|
||||
static int stbi__mul2shorts_valid(short a, short b)
|
||||
// returns 1 if the product of two ints fits in a signed short, 0 on overflow.
|
||||
static int stbi__mul2shorts_valid(int a, int b)
|
||||
{
|
||||
if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
|
||||
if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
|
||||
|
@ -3384,13 +3385,13 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
|
||||
static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
|
||||
{
|
||||
// some JPEGs have junk at end, skip over it but if we find what looks
|
||||
// like a valid marker, resume there
|
||||
while (!stbi__at_eof(j->s)) {
|
||||
int x = stbi__get8(j->s);
|
||||
while (x == 255) { // might be a marker
|
||||
stbi_uc x = stbi__get8(j->s);
|
||||
while (x == 0xff) { // might be a marker
|
||||
if (stbi__at_eof(j->s)) return STBI__MARKER_none;
|
||||
x = stbi__get8(j->s);
|
||||
if (x != 0x00 && x != 0xff) {
|
||||
|
@ -4176,6 +4177,7 @@ typedef struct
|
|||
{
|
||||
stbi_uc *zbuffer, *zbuffer_end;
|
||||
int num_bits;
|
||||
int hit_zeof_once;
|
||||
stbi__uint32 code_buffer;
|
||||
|
||||
char *zout;
|
||||
|
@ -4242,9 +4244,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
|
|||
int b,s;
|
||||
if (a->num_bits < 16) {
|
||||
if (stbi__zeof(a)) {
|
||||
return -1; /* report error for unexpected end of data. */
|
||||
if (!a->hit_zeof_once) {
|
||||
// This is the first time we hit eof, insert 16 extra padding btis
|
||||
// to allow us to keep going; if we actually consume any of them
|
||||
// though, that is invalid data. This is caught later.
|
||||
a->hit_zeof_once = 1;
|
||||
a->num_bits += 16; // add 16 implicit zero bits
|
||||
} else {
|
||||
// We already inserted our extra 16 padding bits and are again
|
||||
// out, this stream is actually prematurely terminated.
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
stbi__fill_bits(a);
|
||||
}
|
||||
stbi__fill_bits(a);
|
||||
}
|
||||
b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
|
||||
if (b) {
|
||||
|
@ -4309,6 +4322,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
|
|||
int len,dist;
|
||||
if (z == 256) {
|
||||
a->zout = zout;
|
||||
if (a->hit_zeof_once && a->num_bits < 16) {
|
||||
// The first time we hit zeof, we inserted 16 extra zero bits into our bit
|
||||
// buffer so the decoder can just do its speculative decoding. But if we
|
||||
// actually consumed any of those bits (which is the case when num_bits < 16),
|
||||
// the stream actually read past the end so it is malformed.
|
||||
return stbi__err("unexpected end","Corrupt PNG");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
|
||||
|
@ -4320,7 +4340,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
|
|||
dist = stbi__zdist_base[z];
|
||||
if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
|
||||
if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
|
||||
if (zout + len > a->zout_end) {
|
||||
if (len > a->zout_end - zout) {
|
||||
if (!stbi__zexpand(a, zout, len)) return 0;
|
||||
zout = a->zout;
|
||||
}
|
||||
|
@ -4464,6 +4484,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
|
|||
if (!stbi__parse_zlib_header(a)) return 0;
|
||||
a->num_bits = 0;
|
||||
a->code_buffer = 0;
|
||||
a->hit_zeof_once = 0;
|
||||
do {
|
||||
final = stbi__zreceive(a,1);
|
||||
type = stbi__zreceive(a,2);
|
||||
|
@ -4619,9 +4640,8 @@ enum {
|
|||
STBI__F_up=2,
|
||||
STBI__F_avg=3,
|
||||
STBI__F_paeth=4,
|
||||
// synthetic filters used for first scanline to avoid needing a dummy row of 0s
|
||||
STBI__F_avg_first,
|
||||
STBI__F_paeth_first
|
||||
// synthetic filter used for first scanline to avoid needing a dummy row of 0s
|
||||
STBI__F_avg_first
|
||||
};
|
||||
|
||||
static stbi_uc first_row_filter[5] =
|
||||
|
@ -4630,29 +4650,56 @@ static stbi_uc first_row_filter[5] =
|
|||
STBI__F_sub,
|
||||
STBI__F_none,
|
||||
STBI__F_avg_first,
|
||||
STBI__F_paeth_first
|
||||
STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
|
||||
};
|
||||
|
||||
static int stbi__paeth(int a, int b, int c)
|
||||
{
|
||||
int p = a + b - c;
|
||||
int pa = abs(p-a);
|
||||
int pb = abs(p-b);
|
||||
int pc = abs(p-c);
|
||||
if (pa <= pb && pa <= pc) return a;
|
||||
if (pb <= pc) return b;
|
||||
return c;
|
||||
// This formulation looks very different from the reference in the PNG spec, but is
|
||||
// actually equivalent and has favorable data dependencies and admits straightforward
|
||||
// generation of branch-free code, which helps performance significantly.
|
||||
int thresh = c*3 - (a + b);
|
||||
int lo = a < b ? a : b;
|
||||
int hi = a < b ? b : a;
|
||||
int t0 = (hi <= thresh) ? lo : c;
|
||||
int t1 = (thresh <= lo) ? hi : t0;
|
||||
return t1;
|
||||
}
|
||||
|
||||
static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
|
||||
|
||||
// adds an extra all-255 alpha channel
|
||||
// dest == src is legal
|
||||
// img_n must be 1 or 3
|
||||
static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)
|
||||
{
|
||||
int i;
|
||||
// must process data backwards since we allow dest==src
|
||||
if (img_n == 1) {
|
||||
for (i=x-1; i >= 0; --i) {
|
||||
dest[i*2+1] = 255;
|
||||
dest[i*2+0] = src[i];
|
||||
}
|
||||
} else {
|
||||
STBI_ASSERT(img_n == 3);
|
||||
for (i=x-1; i >= 0; --i) {
|
||||
dest[i*4+3] = 255;
|
||||
dest[i*4+2] = src[i*3+2];
|
||||
dest[i*4+1] = src[i*3+1];
|
||||
dest[i*4+0] = src[i*3+0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create the png data from post-deflated data
|
||||
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
|
||||
{
|
||||
int bytes = (depth == 16? 2 : 1);
|
||||
int bytes = (depth == 16 ? 2 : 1);
|
||||
stbi__context *s = a->s;
|
||||
stbi__uint32 i,j,stride = x*out_n*bytes;
|
||||
stbi__uint32 img_len, img_width_bytes;
|
||||
stbi_uc *filter_buf;
|
||||
int all_ok = 1;
|
||||
int k;
|
||||
int img_n = s->img_n; // copy it into a local for later
|
||||
|
||||
|
@ -4664,8 +4711,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|||
a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
|
||||
if (!a->out) return stbi__err("outofmem", "Out of memory");
|
||||
|
||||
// note: error exits here don't need to clean up a->out individually,
|
||||
// stbi__do_png always does on error.
|
||||
if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
|
||||
img_width_bytes = (((img_n * x * depth) + 7) >> 3);
|
||||
if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");
|
||||
img_len = (img_width_bytes + 1) * y;
|
||||
|
||||
// we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
|
||||
|
@ -4673,189 +4723,137 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|||
// so just check for raw_len < img_len always.
|
||||
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
|
||||
// Allocate two scan lines worth of filter workspace buffer.
|
||||
filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);
|
||||
if (!filter_buf) return stbi__err("outofmem", "Out of memory");
|
||||
|
||||
// Filtering for low-bit-depth images
|
||||
if (depth < 8) {
|
||||
filter_bytes = 1;
|
||||
width = img_width_bytes;
|
||||
}
|
||||
|
||||
for (j=0; j < y; ++j) {
|
||||
stbi_uc *cur = a->out + stride*j;
|
||||
stbi_uc *prior;
|
||||
// cur/prior filter buffers alternate
|
||||
stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;
|
||||
stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;
|
||||
stbi_uc *dest = a->out + stride*j;
|
||||
int nk = width * filter_bytes;
|
||||
int filter = *raw++;
|
||||
|
||||
if (filter > 4)
|
||||
return stbi__err("invalid filter","Corrupt PNG");
|
||||
|
||||
if (depth < 8) {
|
||||
if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
|
||||
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
|
||||
filter_bytes = 1;
|
||||
width = img_width_bytes;
|
||||
// check filter type
|
||||
if (filter > 4) {
|
||||
all_ok = stbi__err("invalid filter","Corrupt PNG");
|
||||
break;
|
||||
}
|
||||
prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
|
||||
|
||||
// if first row, use special filter that doesn't sample previous row
|
||||
if (j == 0) filter = first_row_filter[filter];
|
||||
|
||||
// handle first byte explicitly
|
||||
for (k=0; k < filter_bytes; ++k) {
|
||||
switch (filter) {
|
||||
case STBI__F_none : cur[k] = raw[k]; break;
|
||||
case STBI__F_sub : cur[k] = raw[k]; break;
|
||||
case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
||||
case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
|
||||
case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
|
||||
case STBI__F_avg_first : cur[k] = raw[k]; break;
|
||||
case STBI__F_paeth_first: cur[k] = raw[k]; break;
|
||||
}
|
||||
// perform actual filtering
|
||||
switch (filter) {
|
||||
case STBI__F_none:
|
||||
memcpy(cur, raw, nk);
|
||||
break;
|
||||
case STBI__F_sub:
|
||||
memcpy(cur, raw, filter_bytes);
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
|
||||
break;
|
||||
case STBI__F_up:
|
||||
for (k = 0; k < nk; ++k)
|
||||
cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
|
||||
break;
|
||||
case STBI__F_avg:
|
||||
for (k = 0; k < filter_bytes; ++k)
|
||||
cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));
|
||||
break;
|
||||
case STBI__F_paeth:
|
||||
for (k = 0; k < filter_bytes; ++k)
|
||||
cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));
|
||||
break;
|
||||
case STBI__F_avg_first:
|
||||
memcpy(cur, raw, filter_bytes);
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));
|
||||
break;
|
||||
}
|
||||
|
||||
if (depth == 8) {
|
||||
if (img_n != out_n)
|
||||
cur[img_n] = 255; // first pixel
|
||||
raw += img_n;
|
||||
cur += out_n;
|
||||
prior += out_n;
|
||||
} else if (depth == 16) {
|
||||
if (img_n != out_n) {
|
||||
cur[filter_bytes] = 255; // first pixel top byte
|
||||
cur[filter_bytes+1] = 255; // first pixel bottom byte
|
||||
}
|
||||
raw += filter_bytes;
|
||||
cur += output_bytes;
|
||||
prior += output_bytes;
|
||||
} else {
|
||||
raw += 1;
|
||||
cur += 1;
|
||||
prior += 1;
|
||||
}
|
||||
raw += nk;
|
||||
|
||||
// this is a little gross, so that we don't switch per-pixel or per-component
|
||||
if (depth < 8 || img_n == out_n) {
|
||||
int nk = (width - 1)*filter_bytes;
|
||||
#define STBI__CASE(f) \
|
||||
case f: \
|
||||
for (k=0; k < nk; ++k)
|
||||
switch (filter) {
|
||||
// "none" filter turns into a memcpy here; make that explicit.
|
||||
case STBI__F_none: memcpy(cur, raw, nk); break;
|
||||
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
|
||||
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
|
||||
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
|
||||
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
|
||||
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
|
||||
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
|
||||
}
|
||||
#undef STBI__CASE
|
||||
raw += nk;
|
||||
} else {
|
||||
STBI_ASSERT(img_n+1 == out_n);
|
||||
#define STBI__CASE(f) \
|
||||
case f: \
|
||||
for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
|
||||
for (k=0; k < filter_bytes; ++k)
|
||||
switch (filter) {
|
||||
STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
|
||||
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
|
||||
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
|
||||
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
|
||||
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
|
||||
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
|
||||
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
|
||||
}
|
||||
#undef STBI__CASE
|
||||
|
||||
// the loop above sets the high byte of the pixels' alpha, but for
|
||||
// 16 bit png files we also need the low byte set. we'll do that here.
|
||||
if (depth == 16) {
|
||||
cur = a->out + stride*j; // start at the beginning of the row again
|
||||
for (i=0; i < x; ++i,cur+=output_bytes) {
|
||||
cur[filter_bytes+1] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we make a separate pass to expand bits to pixels; for performance,
|
||||
// this could run two scanlines behind the above code, so it won't
|
||||
// intefere with filtering but will still be in the cache.
|
||||
if (depth < 8) {
|
||||
for (j=0; j < y; ++j) {
|
||||
stbi_uc *cur = a->out + stride*j;
|
||||
stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes;
|
||||
// unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
|
||||
// png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
|
||||
// expand decoded bits in cur to dest, also adding an extra alpha channel if desired
|
||||
if (depth < 8) {
|
||||
stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
|
||||
stbi_uc *in = cur;
|
||||
stbi_uc *out = dest;
|
||||
stbi_uc inb = 0;
|
||||
stbi__uint32 nsmp = x*img_n;
|
||||
|
||||
// note that the final byte might overshoot and write more data than desired.
|
||||
// we can allocate enough data that this never writes out of memory, but it
|
||||
// could also overwrite the next scanline. can it overwrite non-empty data
|
||||
// on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
|
||||
// so we need to explicitly clamp the final ones
|
||||
|
||||
// expand bits to bytes first
|
||||
if (depth == 4) {
|
||||
for (k=x*img_n; k >= 2; k-=2, ++in) {
|
||||
*cur++ = scale * ((*in >> 4) );
|
||||
*cur++ = scale * ((*in ) & 0x0f);
|
||||
for (i=0; i < nsmp; ++i) {
|
||||
if ((i & 1) == 0) inb = *in++;
|
||||
*out++ = scale * (inb >> 4);
|
||||
inb <<= 4;
|
||||
}
|
||||
if (k > 0) *cur++ = scale * ((*in >> 4) );
|
||||
} else if (depth == 2) {
|
||||
for (k=x*img_n; k >= 4; k-=4, ++in) {
|
||||
*cur++ = scale * ((*in >> 6) );
|
||||
*cur++ = scale * ((*in >> 4) & 0x03);
|
||||
*cur++ = scale * ((*in >> 2) & 0x03);
|
||||
*cur++ = scale * ((*in ) & 0x03);
|
||||
for (i=0; i < nsmp; ++i) {
|
||||
if ((i & 3) == 0) inb = *in++;
|
||||
*out++ = scale * (inb >> 6);
|
||||
inb <<= 2;
|
||||
}
|
||||
if (k > 0) *cur++ = scale * ((*in >> 6) );
|
||||
if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
|
||||
if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
|
||||
} else if (depth == 1) {
|
||||
for (k=x*img_n; k >= 8; k-=8, ++in) {
|
||||
*cur++ = scale * ((*in >> 7) );
|
||||
*cur++ = scale * ((*in >> 6) & 0x01);
|
||||
*cur++ = scale * ((*in >> 5) & 0x01);
|
||||
*cur++ = scale * ((*in >> 4) & 0x01);
|
||||
*cur++ = scale * ((*in >> 3) & 0x01);
|
||||
*cur++ = scale * ((*in >> 2) & 0x01);
|
||||
*cur++ = scale * ((*in >> 1) & 0x01);
|
||||
*cur++ = scale * ((*in ) & 0x01);
|
||||
} else {
|
||||
STBI_ASSERT(depth == 1);
|
||||
for (i=0; i < nsmp; ++i) {
|
||||
if ((i & 7) == 0) inb = *in++;
|
||||
*out++ = scale * (inb >> 7);
|
||||
inb <<= 1;
|
||||
}
|
||||
if (k > 0) *cur++ = scale * ((*in >> 7) );
|
||||
if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
|
||||
if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
|
||||
if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
|
||||
if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
|
||||
if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
|
||||
if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
|
||||
}
|
||||
if (img_n != out_n) {
|
||||
int q;
|
||||
// insert alpha = 255
|
||||
cur = a->out + stride*j;
|
||||
|
||||
// insert alpha=255 values if desired
|
||||
if (img_n != out_n)
|
||||
stbi__create_png_alpha_expand8(dest, dest, x, img_n);
|
||||
} else if (depth == 8) {
|
||||
if (img_n == out_n)
|
||||
memcpy(dest, cur, x*img_n);
|
||||
else
|
||||
stbi__create_png_alpha_expand8(dest, cur, x, img_n);
|
||||
} else if (depth == 16) {
|
||||
// convert the image data from big-endian to platform-native
|
||||
stbi__uint16 *dest16 = (stbi__uint16*)dest;
|
||||
stbi__uint32 nsmp = x*img_n;
|
||||
|
||||
if (img_n == out_n) {
|
||||
for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
|
||||
*dest16 = (cur[0] << 8) | cur[1];
|
||||
} else {
|
||||
STBI_ASSERT(img_n+1 == out_n);
|
||||
if (img_n == 1) {
|
||||
for (q=x-1; q >= 0; --q) {
|
||||
cur[q*2+1] = 255;
|
||||
cur[q*2+0] = cur[q];
|
||||
for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
|
||||
dest16[0] = (cur[0] << 8) | cur[1];
|
||||
dest16[1] = 0xffff;
|
||||
}
|
||||
} else {
|
||||
STBI_ASSERT(img_n == 3);
|
||||
for (q=x-1; q >= 0; --q) {
|
||||
cur[q*4+3] = 255;
|
||||
cur[q*4+2] = cur[q*3+2];
|
||||
cur[q*4+1] = cur[q*3+1];
|
||||
cur[q*4+0] = cur[q*3+0];
|
||||
for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
|
||||
dest16[0] = (cur[0] << 8) | cur[1];
|
||||
dest16[1] = (cur[2] << 8) | cur[3];
|
||||
dest16[2] = (cur[4] << 8) | cur[5];
|
||||
dest16[3] = 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (depth == 16) {
|
||||
// force the image data from big-endian to platform-native.
|
||||
// this is done in a separate pass due to the decoding relying
|
||||
// on the data being untouched, but could probably be done
|
||||
// per-line during decode if care is taken.
|
||||
stbi_uc *cur = a->out;
|
||||
stbi__uint16 *cur16 = (stbi__uint16*)cur;
|
||||
|
||||
for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
|
||||
*cur16 = (cur[0] << 8) | cur[1];
|
||||
}
|
||||
}
|
||||
|
||||
STBI_FREE(filter_buf);
|
||||
if (!all_ok) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
1298
stb_image_resize2.h
1298
stb_image_resize2.h
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,259 @@
|
|||
filename,width,height,ncomp,error,hash
|
||||
pngsuite/16bit/basi0g16.png,32,32,1,,0xfc8f2f99
|
||||
pngsuite/16bit/basi2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/16bit/basi4a16.png,32,32,2,,0x198cf245
|
||||
pngsuite/16bit/basi6a16.png,32,32,4,,0x3016e9b5
|
||||
pngsuite/16bit/basn0g16.png,32,32,1,,0xfc8f2f99
|
||||
pngsuite/16bit/basn2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/16bit/basn4a16.png,32,32,2,,0x198cf245
|
||||
pngsuite/16bit/basn6a16.png,32,32,4,,0x3016e9b5
|
||||
pngsuite/16bit/bgai4a16.png,32,32,2,,0x198cf245
|
||||
pngsuite/16bit/bgan6a16.png,32,32,4,,0x3016e9b5
|
||||
pngsuite/16bit/bggn4a16.png,32,32,2,,0x198cf245
|
||||
pngsuite/16bit/bgyn6a16.png,32,32,4,,0x3016e9b5
|
||||
pngsuite/16bit/oi1n0g16.png,32,32,1,,0xfc8f2f99
|
||||
pngsuite/16bit/oi1n2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/16bit/oi2n0g16.png,32,32,1,,0xfc8f2f99
|
||||
pngsuite/16bit/oi2n2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/16bit/oi4n0g16.png,32,32,1,,0xfc8f2f99
|
||||
pngsuite/16bit/oi4n2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/16bit/oi9n0g16.png,32,32,1,,0xfc8f2f99
|
||||
pngsuite/16bit/oi9n2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/16bit/tbbn2c16.png,32,32,4,,0xaa9bfe44
|
||||
pngsuite/16bit/tbgn2c16.png,32,32,4,,0xaa9bfe44
|
||||
pngsuite/16bit/tbwn0g16.png,32,32,2,,0x075e519a
|
||||
pngsuite/corrupt/xc1n0g08.png,32,32,2,bad ctype,0x00000000
|
||||
pngsuite/corrupt/xc9n2c08.png,32,32,2,bad ctype,0x00000000
|
||||
pngsuite/corrupt/xcrn0g04.png,32,32,2,unknown image type,0x00000000
|
||||
pngsuite/corrupt/xcsn0g01.png,32,32,1,,0x43b9891f
|
||||
pngsuite/corrupt/xd0n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
|
||||
pngsuite/corrupt/xd3n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
|
||||
pngsuite/corrupt/xd9n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
|
||||
pngsuite/corrupt/xdtn0g01.png,32,32,1,no IDAT,0x00000000
|
||||
pngsuite/corrupt/xhdn0g08.png,32,32,1,,0x414f1ca9
|
||||
pngsuite/corrupt/xlfn0g04.png,32,32,1,unknown image type,0x00000000
|
||||
pngsuite/corrupt/xs1n0g01.png,32,32,1,unknown image type,0x00000000
|
||||
pngsuite/corrupt/xs2n0g01.png,32,32,1,unknown image type,0x00000000
|
||||
pngsuite/corrupt/xs4n0g01.png,32,32,1,unknown image type,0x00000000
|
||||
pngsuite/corrupt/xs7n0g01.png,32,32,1,unknown image type,0x00000000
|
||||
pngsuite/iphone/iphone_basi0g01.png,32,32,4,,0x5fb33cfd
|
||||
pngsuite/iphone/iphone_basi0g02.png,32,32,4,,0x5bbe95c5
|
||||
pngsuite/iphone/iphone_basi3p02.png,32,32,4,,0x50ba29c5
|
||||
pngsuite/iphone/iphone_bgwn6a08.png,32,32,4,,0x45d8548a
|
||||
pngsuite/iphone/iphone_bgyn6a16.png,32,32,4,,0x4b2b7545
|
||||
pngsuite/iphone/iphone_tbyn3p08.png,32,32,4,,0x8ea9aaaf
|
||||
pngsuite/iphone/iphone_z06n2c08.png,32,32,4,,0xb5dd034b
|
||||
pngsuite/primary/basi0g01.png,32,32,1,,0x43b9891f
|
||||
pngsuite/primary/basi0g02.png,32,32,1,,0xaf0bb3c5
|
||||
pngsuite/primary/basi0g04.png,32,32,1,,0x6fbaeb45
|
||||
pngsuite/primary/basi0g08.png,32,32,1,,0x414f1ca9
|
||||
pngsuite/primary/basi2c08.png,32,32,3,,0x522345c5
|
||||
pngsuite/primary/basi3p01.png,32,32,3,,0x9c5b75c5
|
||||
pngsuite/primary/basi3p02.png,32,32,3,,0x46f26ec5
|
||||
pngsuite/primary/basi3p04.png,32,32,3,,0x35b2e4a5
|
||||
pngsuite/primary/basi3p08.png,32,32,3,,0xfe066865
|
||||
pngsuite/primary/basi4a08.png,32,32,2,,0x77cbbfa5
|
||||
pngsuite/primary/basi6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary/basn0g01.png,32,32,1,,0x43b9891f
|
||||
pngsuite/primary/basn0g02.png,32,32,1,,0xaf0bb3c5
|
||||
pngsuite/primary/basn0g04.png,32,32,1,,0x6fbaeb45
|
||||
pngsuite/primary/basn0g08.png,32,32,1,,0x414f1ca9
|
||||
pngsuite/primary/basn2c08.png,32,32,3,,0x522345c5
|
||||
pngsuite/primary/basn3p01.png,32,32,3,,0x9c5b75c5
|
||||
pngsuite/primary/basn3p02.png,32,32,3,,0x46f26ec5
|
||||
pngsuite/primary/basn3p04.png,32,32,3,,0x35b2e4a5
|
||||
pngsuite/primary/basn3p08.png,32,32,3,,0xfe066865
|
||||
pngsuite/primary/basn4a08.png,32,32,2,,0x77cbbfa5
|
||||
pngsuite/primary/basn6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary/bgai4a08.png,32,32,2,,0x77cbbfa5
|
||||
pngsuite/primary/bgan6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary/bgbn4a08.png,32,32,2,,0x77cbbfa5
|
||||
pngsuite/primary/bgwn6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary/s01i3p01.png,1,1,3,,0xafb003b6
|
||||
pngsuite/primary/s01n3p01.png,1,1,3,,0xafb003b6
|
||||
pngsuite/primary/s02i3p01.png,2,2,3,,0x96f3dd85
|
||||
pngsuite/primary/s02n3p01.png,2,2,3,,0x96f3dd85
|
||||
pngsuite/primary/s03i3p01.png,3,3,3,,0xb0cf1241
|
||||
pngsuite/primary/s03n3p01.png,3,3,3,,0xb0cf1241
|
||||
pngsuite/primary/s04i3p01.png,4,4,3,,0xbfcedd75
|
||||
pngsuite/primary/s04n3p01.png,4,4,3,,0xbfcedd75
|
||||
pngsuite/primary/s05i3p02.png,5,5,3,,0xc322cedd
|
||||
pngsuite/primary/s05n3p02.png,5,5,3,,0xc322cedd
|
||||
pngsuite/primary/s06i3p02.png,6,6,3,,0x46916799
|
||||
pngsuite/primary/s06n3p02.png,6,6,3,,0x46916799
|
||||
pngsuite/primary/s07i3p02.png,7,7,3,,0xfdabc297
|
||||
pngsuite/primary/s07n3p02.png,7,7,3,,0xfdabc297
|
||||
pngsuite/primary/s08i3p02.png,8,8,3,,0x8f036d09
|
||||
pngsuite/primary/s08n3p02.png,8,8,3,,0x8f036d09
|
||||
pngsuite/primary/s09i3p02.png,9,9,3,,0x16a46830
|
||||
pngsuite/primary/s09n3p02.png,9,9,3,,0x16a46830
|
||||
pngsuite/primary/s32i3p04.png,32,32,3,,0x4bd4fbd3
|
||||
pngsuite/primary/s32n3p04.png,32,32,3,,0x4bd4fbd3
|
||||
pngsuite/primary/s33i3p04.png,33,33,3,,0x51aa005e
|
||||
pngsuite/primary/s33n3p04.png,33,33,3,,0x51aa005e
|
||||
pngsuite/primary/s34i3p04.png,34,34,3,,0x84818775
|
||||
pngsuite/primary/s34n3p04.png,34,34,3,,0x84818775
|
||||
pngsuite/primary/s35i3p04.png,35,35,3,,0x6359ec75
|
||||
pngsuite/primary/s35n3p04.png,35,35,3,,0x6359ec75
|
||||
pngsuite/primary/s36i3p04.png,36,36,3,,0xe4878065
|
||||
pngsuite/primary/s36n3p04.png,36,36,3,,0xe4878065
|
||||
pngsuite/primary/s37i3p04.png,37,37,3,,0x3cefc423
|
||||
pngsuite/primary/s37n3p04.png,37,37,3,,0x3cefc423
|
||||
pngsuite/primary/s38i3p04.png,38,38,3,,0xffc55a2b
|
||||
pngsuite/primary/s38n3p04.png,38,38,3,,0xffc55a2b
|
||||
pngsuite/primary/s39i3p04.png,39,39,3,,0x0c790240
|
||||
pngsuite/primary/s39n3p04.png,39,39,3,,0x0c790240
|
||||
pngsuite/primary/s40i3p04.png,40,40,3,,0x951a316d
|
||||
pngsuite/primary/s40n3p04.png,40,40,3,,0x951a316d
|
||||
pngsuite/primary/tbbn0g04.png,32,32,2,,0x9c8410ea
|
||||
pngsuite/primary/tbbn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary/tbgn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary/tbrn2c08.png,32,32,4,,0xaa9bfe44
|
||||
pngsuite/primary/tbwn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary/tbyn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary/tm3n3p02.png,32,32,4,,0xf59745c5
|
||||
pngsuite/primary/tp0n0g08.png,32,32,1,,0xbac0864c
|
||||
pngsuite/primary/tp0n2c08.png,32,32,3,,0x82687c37
|
||||
pngsuite/primary/tp0n3p08.png,32,32,3,,0x61f54e37
|
||||
pngsuite/primary/tp1n3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary/z00n2c08.png,32,32,3,,0x65b4a72f
|
||||
pngsuite/primary/z03n2c08.png,32,32,3,,0x65b4a72f
|
||||
pngsuite/primary/z06n2c08.png,32,32,3,,0x65b4a72f
|
||||
pngsuite/primary/z09n2c08.png,32,32,3,,0x65b4a72f
|
||||
pngsuite/primary_check/basi0g01.png,32,32,4,,0x5fb33cfd
|
||||
pngsuite/primary_check/basi0g02.png,32,32,4,,0x5bbe95c5
|
||||
pngsuite/primary_check/basi0g04.png,32,32,4,,0x3468b9c5
|
||||
pngsuite/primary_check/basi0g08.png,32,32,4,,0x262ef46d
|
||||
pngsuite/primary_check/basi2c08.png,32,32,4,,0x1fc92bc5
|
||||
pngsuite/primary_check/basi3p01.png,32,32,4,,0x28a3e1c5
|
||||
pngsuite/primary_check/basi3p02.png,32,32,4,,0x803be5c5
|
||||
pngsuite/primary_check/basi3p04.png,32,32,4,,0xf3fc60e5
|
||||
pngsuite/primary_check/basi3p08.png,32,32,4,,0x30ef4f45
|
||||
pngsuite/primary_check/basi4a08.png,32,32,4,,0x23c8536d
|
||||
pngsuite/primary_check/basi6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary_check/basn0g01.png,32,32,4,,0x5fb33cfd
|
||||
pngsuite/primary_check/basn0g02.png,32,32,4,,0x5bbe95c5
|
||||
pngsuite/primary_check/basn0g04.png,32,32,4,,0x3468b9c5
|
||||
pngsuite/primary_check/basn0g08.png,32,32,4,,0x262ef46d
|
||||
pngsuite/primary_check/basn2c08.png,32,32,4,,0x1fc92bc5
|
||||
pngsuite/primary_check/basn3p01.png,32,32,4,,0x28a3e1c5
|
||||
pngsuite/primary_check/basn3p02.png,32,32,4,,0x803be5c5
|
||||
pngsuite/primary_check/basn3p04.png,32,32,4,,0xf3fc60e5
|
||||
pngsuite/primary_check/basn3p08.png,32,32,4,,0x30ef4f45
|
||||
pngsuite/primary_check/basn4a08.png,32,32,4,,0x23c8536d
|
||||
pngsuite/primary_check/basn6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary_check/bgai4a08.png,32,32,4,,0x23c8536d
|
||||
pngsuite/primary_check/bgan6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary_check/bgbn4a08.png,32,32,4,,0x23c8536d
|
||||
pngsuite/primary_check/bgwn6a08.png,32,32,4,,0xb472197d
|
||||
pngsuite/primary_check/s01i3p01.png,1,1,4,,0xdb152beb
|
||||
pngsuite/primary_check/s01n3p01.png,1,1,4,,0xdb152beb
|
||||
pngsuite/primary_check/s02i3p01.png,2,2,4,,0xa344a3a5
|
||||
pngsuite/primary_check/s02n3p01.png,2,2,4,,0xa344a3a5
|
||||
pngsuite/primary_check/s03i3p01.png,3,3,4,,0x594d3bfa
|
||||
pngsuite/primary_check/s03n3p01.png,3,3,4,,0x594d3bfa
|
||||
pngsuite/primary_check/s04i3p01.png,4,4,4,,0xd59d4605
|
||||
pngsuite/primary_check/s04n3p01.png,4,4,4,,0xd59d4605
|
||||
pngsuite/primary_check/s05i3p02.png,5,5,4,,0x41e58366
|
||||
pngsuite/primary_check/s05n3p02.png,5,5,4,,0x41e58366
|
||||
pngsuite/primary_check/s06i3p02.png,6,6,4,,0xcad1a885
|
||||
pngsuite/primary_check/s06n3p02.png,6,6,4,,0xcad1a885
|
||||
pngsuite/primary_check/s07i3p02.png,7,7,4,,0x09184108
|
||||
pngsuite/primary_check/s07n3p02.png,7,7,4,,0x09184108
|
||||
pngsuite/primary_check/s08i3p02.png,8,8,4,,0x4fd11cad
|
||||
pngsuite/primary_check/s08n3p02.png,8,8,4,,0x4fd11cad
|
||||
pngsuite/primary_check/s09i3p02.png,9,9,4,,0xc50dbecd
|
||||
pngsuite/primary_check/s09n3p02.png,9,9,4,,0xc50dbecd
|
||||
pngsuite/primary_check/s32i3p04.png,32,32,4,,0x95cbb1d3
|
||||
pngsuite/primary_check/s32n3p04.png,32,32,4,,0x95cbb1d3
|
||||
pngsuite/primary_check/s33i3p04.png,33,33,4,,0x6649fc5b
|
||||
pngsuite/primary_check/s33n3p04.png,33,33,4,,0x6649fc5b
|
||||
pngsuite/primary_check/s34i3p04.png,34,34,4,,0x35b98e15
|
||||
pngsuite/primary_check/s34n3p04.png,34,34,4,,0x35b98e15
|
||||
pngsuite/primary_check/s35i3p04.png,35,35,4,,0xc9ddf938
|
||||
pngsuite/primary_check/s35n3p04.png,35,35,4,,0xc9ddf938
|
||||
pngsuite/primary_check/s36i3p04.png,36,36,4,,0x7bb4e1cd
|
||||
pngsuite/primary_check/s36n3p04.png,36,36,4,,0x7bb4e1cd
|
||||
pngsuite/primary_check/s37i3p04.png,37,37,4,,0xee50001c
|
||||
pngsuite/primary_check/s37n3p04.png,37,37,4,,0xee50001c
|
||||
pngsuite/primary_check/s38i3p04.png,38,38,4,,0x51b76813
|
||||
pngsuite/primary_check/s38n3p04.png,38,38,4,,0x51b76813
|
||||
pngsuite/primary_check/s39i3p04.png,39,39,4,,0x42f23327
|
||||
pngsuite/primary_check/s39n3p04.png,39,39,4,,0x42f23327
|
||||
pngsuite/primary_check/s40i3p04.png,40,40,4,,0xf91b6a7d
|
||||
pngsuite/primary_check/s40n3p04.png,40,40,4,,0xf91b6a7d
|
||||
pngsuite/primary_check/tbbn0g04.png,32,32,4,,0x8a0117a4
|
||||
pngsuite/primary_check/tbbn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary_check/tbgn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary_check/tbrn2c08.png,32,32,4,,0xaa9bfe44
|
||||
pngsuite/primary_check/tbwn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary_check/tbyn3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary_check/tm3n3p02.png,32,32,4,,0xf59745c5
|
||||
pngsuite/primary_check/tp0n0g08.png,32,32,4,,0xd405ad2e
|
||||
pngsuite/primary_check/tp0n2c08.png,32,32,4,,0x5a66ca09
|
||||
pngsuite/primary_check/tp0n3p08.png,32,32,4,,0x06e81adf
|
||||
pngsuite/primary_check/tp1n3p08.png,32,32,4,,0x82bf9a57
|
||||
pngsuite/primary_check/z00n2c08.png,32,32,4,,0xaa698493
|
||||
pngsuite/primary_check/z03n2c08.png,32,32,4,,0xaa698493
|
||||
pngsuite/primary_check/z06n2c08.png,32,32,4,,0xaa698493
|
||||
pngsuite/primary_check/z09n2c08.png,32,32,4,,0xaa698493
|
||||
pngsuite/unused/ccwn2c08.png,32,32,3,,0xbb576418
|
||||
pngsuite/unused/ccwn3p08.png,32,32,3,,0x5c4df060
|
||||
pngsuite/unused/cdfn2c08.png,8,32,3,,0xe30ed48f
|
||||
pngsuite/unused/cdhn2c08.png,32,8,3,,0x999321f5
|
||||
pngsuite/unused/cdsn2c08.png,8,8,3,,0x7f63fa01
|
||||
pngsuite/unused/cdun2c08.png,32,32,3,,0xbd325d71
|
||||
pngsuite/unused/ch1n3p04.png,32,32,3,,0x35b2e4a5
|
||||
pngsuite/unused/ch2n3p08.png,32,32,3,,0xfe066865
|
||||
pngsuite/unused/cm0n0g04.png,32,32,1,,0xe9f53e6c
|
||||
pngsuite/unused/cm7n0g04.png,32,32,1,,0xe9f53e6c
|
||||
pngsuite/unused/cm9n0g04.png,32,32,1,,0xe9f53e6c
|
||||
pngsuite/unused/cs3n2c16.png,32,32,3,,0x7f0fa2c5
|
||||
pngsuite/unused/cs3n3p08.png,32,32,3,,0x5533bac5
|
||||
pngsuite/unused/cs5n2c08.png,32,32,3,,0x8a80f8c5
|
||||
pngsuite/unused/cs5n3p08.png,32,32,3,,0x8a80f8c5
|
||||
pngsuite/unused/cs8n2c08.png,32,32,3,,0x7f0fa2c5
|
||||
pngsuite/unused/cs8n3p08.png,32,32,3,,0x7f0fa2c5
|
||||
pngsuite/unused/ct0n0g04.png,32,32,1,,0xe9f53e6c
|
||||
pngsuite/unused/ct1n0g04.png,32,32,1,,0xe9f53e6c
|
||||
pngsuite/unused/cten0g04.png,32,32,1,,0x1c073b45
|
||||
pngsuite/unused/ctfn0g04.png,32,32,1,,0xfa9fd205
|
||||
pngsuite/unused/ctgn0g04.png,32,32,1,,0xf28c8085
|
||||
pngsuite/unused/cthn0g04.png,32,32,1,,0x7c039595
|
||||
pngsuite/unused/ctjn0g04.png,32,32,1,,0xc520f455
|
||||
pngsuite/unused/ctzn0g04.png,32,32,1,,0xe9f53e6c
|
||||
pngsuite/unused/f00n0g08.png,32,32,1,,0x21db411b
|
||||
pngsuite/unused/f00n2c08.png,32,32,3,,0x1f25ded0
|
||||
pngsuite/unused/f01n0g08.png,32,32,1,,0x7437b32a
|
||||
pngsuite/unused/f01n2c08.png,32,32,3,,0x0d4507ae
|
||||
pngsuite/unused/f02n0g08.png,32,32,1,,0x6b633c7c
|
||||
pngsuite/unused/f02n2c08.png,32,32,3,,0x4b278986
|
||||
pngsuite/unused/f03n0g08.png,32,32,1,,0x2f31c08e
|
||||
pngsuite/unused/f03n2c08.png,32,32,3,,0x843ecc7e
|
||||
pngsuite/unused/f04n0g08.png,32,32,1,,0xfd3a0b73
|
||||
pngsuite/unused/f04n2c08.png,32,32,3,,0x557174bc
|
||||
pngsuite/unused/f99n0g04.png,32,32,1,,0xb79aa6e1
|
||||
pngsuite/unused/g03n0g16.png,32,32,1,,0xecd13817
|
||||
pngsuite/unused/g03n2c08.png,32,32,3,,0x242407a8
|
||||
pngsuite/unused/g03n3p04.png,32,32,3,,0xe801ecc8
|
||||
pngsuite/unused/g04n0g16.png,32,32,1,,0xc11bc972
|
||||
pngsuite/unused/g04n2c08.png,32,32,3,,0xdf843cc4
|
||||
pngsuite/unused/g04n3p04.png,32,32,3,,0x60e41f3b
|
||||
pngsuite/unused/g05n0g16.png,32,32,1,,0xbe6615a5
|
||||
pngsuite/unused/g05n2c08.png,32,32,3,,0x5c312116
|
||||
pngsuite/unused/g05n3p04.png,32,32,3,,0x2e0fbf86
|
||||
pngsuite/unused/g07n0g16.png,32,32,1,,0x2b54a398
|
||||
pngsuite/unused/g07n2c08.png,32,32,3,,0xf765fb10
|
||||
pngsuite/unused/g07n3p04.png,32,32,3,,0x9a8c3338
|
||||
pngsuite/unused/g10n0g16.png,32,32,1,,0xb08a92e1
|
||||
pngsuite/unused/g10n2c08.png,32,32,3,,0xa43f2291
|
||||
pngsuite/unused/g10n3p04.png,32,32,3,,0xb733194c
|
||||
pngsuite/unused/g25n0g16.png,32,32,1,,0xa6b1f5dd
|
||||
pngsuite/unused/g25n2c08.png,32,32,3,,0x767aee0c
|
||||
pngsuite/unused/g25n3p04.png,32,32,3,,0x4cf349a8
|
||||
pngsuite/unused/pp0n2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/unused/pp0n6a08.png,32,32,4,,0x3188c645
|
||||
pngsuite/unused/ps1n0g08.png,32,32,1,,0x414f1ca9
|
||||
pngsuite/unused/ps1n2c16.png,32,32,3,,0x65567ed5
|
||||
pngsuite/unused/ps2n0g08.png,32,32,1,,0x414f1ca9
|
||||
pngsuite/unused/ps2n2c16.png,32,32,3,,0x65567ed5
|
|
|
@ -0,0 +1,47 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Reference Paeth filter as per PNG spec
|
||||
static int ref_paeth(int a, int b, int c)
|
||||
{
|
||||
int p = a + b - c;
|
||||
int pa = abs(p-a);
|
||||
int pb = abs(p-b);
|
||||
int pc = abs(p-c);
|
||||
if (pa <= pb && pa <= pc) return a;
|
||||
if (pb <= pc) return b;
|
||||
return c;
|
||||
}
|
||||
|
||||
// Optimized Paeth filter
|
||||
static int opt_paeth(int a, int b, int c)
|
||||
{
|
||||
int thresh = c*3 - (a + b);
|
||||
int lo = a < b ? a : b;
|
||||
int hi = a < b ? b : a;
|
||||
int t0 = (hi <= thresh) ? lo : c;
|
||||
int t1 = (thresh <= lo) ? hi : t0;
|
||||
return t1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Exhaustively test the functions match for all byte inputs a, b,c in [0,255]
|
||||
for (int i = 0; i < (1 << 24); ++i) {
|
||||
int a = i & 0xff;
|
||||
int b = (i >> 8) & 0xff;
|
||||
int c = (i >> 16) & 0xff;
|
||||
|
||||
int ref = ref_paeth(a, b, c);
|
||||
int opt = opt_paeth(a, b, c);
|
||||
if (ref != opt) {
|
||||
fprintf(stderr, "mismatch at a=%3d b=%3d c=%3d: ref=%3d opt=%3d\n", a, b, c, ref, opt);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("all ok!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim:sw=3:sts=3:et
|
|
@ -0,0 +1,75 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define STBI_WINDOWS_UTF8
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32 // what stb.h checks
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#endif
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
#define STB_DEFINE
|
||||
#include "deprecated/stb.h"
|
||||
|
||||
static unsigned int fnv1a_hash32(const stbi_uc *bytes, size_t len)
|
||||
{
|
||||
unsigned int hash = 0x811c9dc5;
|
||||
unsigned int mul = 0x01000193;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
hash = (hash ^ bytes[i]) * mul;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
// The idea for this test is to leave pngsuite/ref_results.csv checked in,
|
||||
// and then you can run this test after making PNG loader changes. If the
|
||||
// ref results change (as per git diff), confirm that the change was
|
||||
// intentional. If so, commit them as well; if not, undo.
|
||||
int main()
|
||||
{
|
||||
char **files;
|
||||
FILE *csv_file;
|
||||
int i;
|
||||
|
||||
files = stb_readdir_recursive("pngsuite", "*.png");
|
||||
if (!files) {
|
||||
fprintf(stderr, "pngsuite files not found!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// sort files by name
|
||||
qsort(files, stb_arr_len(files), sizeof(char*), stb_qsort_strcmp(0));
|
||||
|
||||
csv_file = fopen("pngsuite/ref_results.csv", "w");
|
||||
if (!csv_file) {
|
||||
fprintf(stderr, "error opening ref results for writing!\n");
|
||||
stb_readdir_free(files);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(csv_file, "filename,width,height,ncomp,error,hash\n");
|
||||
for (i = 0; i < stb_arr_len(files); ++i) {
|
||||
char *filename = files[i];
|
||||
int width, height, ncomp;
|
||||
stbi_uc *pixels = stbi_load(filename, &width, &height, &ncomp, 0);
|
||||
const char *error = "";
|
||||
unsigned int hash = 0;
|
||||
|
||||
if (!pixels)
|
||||
error = stbi_failure_reason();
|
||||
else {
|
||||
hash = fnv1a_hash32(pixels, width * height * ncomp);
|
||||
stbi_image_free(pixels);
|
||||
}
|
||||
|
||||
fprintf(csv_file, "%s,%d,%d,%d,%s,0x%08x\n", filename, width, height, ncomp, error, hash);
|
||||
}
|
||||
|
||||
fclose(csv_file);
|
||||
stb_readdir_free(files);
|
||||
}
|
|
@ -3,6 +3,8 @@ stb
|
|||
|
||||
single-file public domain (or MIT licensed) libraries for C/C++
|
||||
|
||||
# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries.
|
||||
|
||||
Noteworthy:
|
||||
|
||||
* image loader: [stb_image.h](stb_image.h)
|
||||
|
@ -11,8 +13,8 @@ Noteworthy:
|
|||
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
|
||||
* typesafe containers: [stb_ds.h](stb_ds.h)
|
||||
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts.
|
||||
|
||||
<a name="stb_libs"></a>
|
||||
|
||||
|
|
Loading…
Reference in New Issue