mirror of https://github.com/nothings/stb.git
Compare commits
22 Commits
cc335c4568
...
f53973e245
Author | SHA1 | Date |
---|---|---|
Scr3amer | f53973e245 | |
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 | |
Scr3amer | 722662eeda | |
Scr3amer | 638236d271 |
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
*.obj
|
||||
*.exe
|
10
README.md
10
README.md
|
@ -15,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>
|
||||
|
||||
|
@ -24,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++
|
||||
|
@ -45,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
|
||||
|
|
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
|
@ -1625,7 +1625,7 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in
|
|||
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
|
||||
{
|
||||
if (info->cff.size) {
|
||||
stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
|
||||
return stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
|
||||
} else {
|
||||
int g = stbtt__GetGlyfOffset(info, glyph_index);
|
||||
if (g < 0) return 0;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -13,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