mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-03-28 05:43:58 +00:00
update stb_* codes to latest master (5c205738c191bcb0abc65c4febfa9bd25ff35234)
wget https://raw.githubusercontent.com/nothings/stb/master/stb_image.h -O src/client/refresh/files/stb_image.h wget https://raw.githubusercontent.com/nothings/stb/master/stb_image_write.h -O src/client/vid/header/stb_image_write.h
This commit is contained in:
parent
b8a6f2b760
commit
074c938c56
3 changed files with 389 additions and 283 deletions
|
@ -65,7 +65,7 @@ option(CURL_SUPPORT "cURL support" ON)
|
|||
option(OPENAL_SUPPORT "OpenAL support" ON)
|
||||
option(SYSTEMWIDE_SUPPORT "Enable systemwide installation of game assets" OFF)
|
||||
option(SDL3_SUPPORT "Build against SDL 3 instead of SDL2" OFF)
|
||||
option(GL1_RENDERER "Build the GL3 renderer" ON)
|
||||
option(GL1_RENDERER "Build the GL1 renderer" ON)
|
||||
option(GL3_RENDERER "Build the GL3 renderer" ON)
|
||||
option(GLES1_RENDERER "Build the GLES1 renderer" OFF)
|
||||
option(GLES3_RENDERER "Build the GLES3 renderer" ON)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
|
||||
/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Do this:
|
||||
|
@ -48,6 +48,8 @@ LICENSE
|
|||
|
||||
RECENT REVISION HISTORY:
|
||||
|
||||
2.30 (2024-05-31) avoid erroneous gcc warning
|
||||
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 +1074,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 +3386,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 +4178,7 @@ typedef struct
|
|||
{
|
||||
stbi_uc *zbuffer, *zbuffer_end;
|
||||
int num_bits;
|
||||
int hit_zeof_once;
|
||||
stbi__uint32 code_buffer;
|
||||
|
||||
char *zout;
|
||||
|
@ -4242,9 +4245,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 +4323,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 +4341,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 +4485,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 +4641,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 +4651,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 +4712,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 +4724,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;
|
||||
}
|
||||
|
||||
|
@ -5161,9 +5160,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||
// non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
|
||||
if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
|
||||
if (z->depth == 16) {
|
||||
for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
|
||||
for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning
|
||||
tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
|
||||
} else {
|
||||
for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
|
||||
for (k = 0; k < s->img_n && k < 3; ++k)
|
||||
tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* stb_image_write - v1.13 - public domain - http://nothings.org/stb
|
||||
/* stb_image_write - v1.16 - public domain - http://nothings.org/stb
|
||||
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
|
@ -105,7 +105,7 @@ USAGE:
|
|||
|
||||
TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
|
||||
data, set the global variable 'stbi_write_tga_with_rle' to 0.
|
||||
|
||||
|
||||
JPEG does ignore alpha channels in input data; quality is between 1 and 100.
|
||||
Higher quality looks better but results in a bigger image.
|
||||
JPEG baseline (no JPEG progressive).
|
||||
|
@ -113,7 +113,7 @@ USAGE:
|
|||
CREDITS:
|
||||
|
||||
|
||||
Sean Barrett - PNG/BMP/TGA
|
||||
Sean Barrett - PNG/BMP/TGA
|
||||
Baldur Karlsson - HDR
|
||||
Jean-Sebastien Guay - TGA monochrome
|
||||
Tim Kelsey - misc enhancements
|
||||
|
@ -140,6 +140,7 @@ CREDITS:
|
|||
Ivan Tikhonov
|
||||
github:ignotion
|
||||
Adam Schackart
|
||||
Andrew Kensler
|
||||
|
||||
LICENSE
|
||||
|
||||
|
@ -166,9 +167,9 @@ LICENSE
|
|||
#endif
|
||||
|
||||
#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
|
||||
extern int stbi_write_tga_with_rle;
|
||||
extern int stbi_write_png_compression_level;
|
||||
extern int stbi_write_force_png_filter;
|
||||
STBIWDEF int stbi_write_tga_with_rle;
|
||||
STBIWDEF int stbi_write_png_compression_level;
|
||||
STBIWDEF int stbi_write_force_png_filter;
|
||||
#endif
|
||||
|
||||
#ifndef STBI_WRITE_NO_STDIO
|
||||
|
@ -178,7 +179,7 @@ STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const
|
|||
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
|
||||
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
|
||||
|
||||
#ifdef STBI_WINDOWS_UTF8
|
||||
#ifdef STBIW_WINDOWS_UTF8
|
||||
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -247,17 +248,17 @@ STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
|
|||
#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
|
||||
|
||||
#ifdef STB_IMAGE_WRITE_STATIC
|
||||
static int stbi__flip_vertically_on_write=0;
|
||||
static int stbi_write_png_compression_level = 8;
|
||||
static int stbi_write_tga_with_rle = 1;
|
||||
static int stbi_write_force_png_filter = -1;
|
||||
#else
|
||||
int stbi_write_png_compression_level = 8;
|
||||
int stbi__flip_vertically_on_write=0;
|
||||
int stbi_write_tga_with_rle = 1;
|
||||
int stbi_write_force_png_filter = -1;
|
||||
#endif
|
||||
|
||||
static int stbi__flip_vertically_on_write = 0;
|
||||
|
||||
STBIWDEF void stbi_flip_vertically_on_write(int flag)
|
||||
{
|
||||
stbi__flip_vertically_on_write = flag;
|
||||
|
@ -267,6 +268,8 @@ typedef struct
|
|||
{
|
||||
stbi_write_func *func;
|
||||
void *context;
|
||||
unsigned char buffer[64];
|
||||
int buf_used;
|
||||
} stbi__write_context;
|
||||
|
||||
// initialize a callback-based context
|
||||
|
@ -283,7 +286,7 @@ static void stbi__stdio_write(void *context, void *data, int size)
|
|||
fwrite(data,1,size,(FILE*) context);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
|
||||
#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
|
||||
#ifdef __cplusplus
|
||||
#define STBIW_EXTERN extern "C"
|
||||
#else
|
||||
|
@ -294,25 +297,25 @@ STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned in
|
|||
|
||||
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
|
||||
{
|
||||
return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
|
||||
return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static FILE *stbiw__fopen(char const *filename, char const *mode)
|
||||
{
|
||||
FILE *f;
|
||||
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
|
||||
#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
|
||||
wchar_t wMode[64];
|
||||
wchar_t wFilename[1024];
|
||||
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
|
||||
return 0;
|
||||
|
||||
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
|
||||
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
|
||||
return 0;
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
if (0 != _wfopen_s(&f, wFilename, wMode))
|
||||
f = 0;
|
||||
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
|
||||
return 0;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
if (0 != _wfopen_s(&f, wFilename, wMode))
|
||||
f = 0;
|
||||
#else
|
||||
f = _wfopen(wFilename, wMode);
|
||||
#endif
|
||||
|
@ -380,16 +383,36 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
|
|||
va_end(v);
|
||||
}
|
||||
|
||||
static void stbiw__write_flush(stbi__write_context *s)
|
||||
{
|
||||
if (s->buf_used) {
|
||||
s->func(s->context, &s->buffer, s->buf_used);
|
||||
s->buf_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void stbiw__putc(stbi__write_context *s, unsigned char c)
|
||||
{
|
||||
s->func(s->context, &c, 1);
|
||||
}
|
||||
|
||||
static void stbiw__write1(stbi__write_context *s, unsigned char a)
|
||||
{
|
||||
if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
|
||||
stbiw__write_flush(s);
|
||||
s->buffer[s->buf_used++] = a;
|
||||
}
|
||||
|
||||
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
|
||||
{
|
||||
unsigned char arr[3];
|
||||
arr[0] = a; arr[1] = b; arr[2] = c;
|
||||
s->func(s->context, arr, 3);
|
||||
int n;
|
||||
if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
|
||||
stbiw__write_flush(s);
|
||||
n = s->buf_used;
|
||||
s->buf_used = n+3;
|
||||
s->buffer[n+0] = a;
|
||||
s->buffer[n+1] = b;
|
||||
s->buffer[n+2] = c;
|
||||
}
|
||||
|
||||
static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
|
||||
|
@ -398,7 +421,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
int k;
|
||||
|
||||
if (write_alpha < 0)
|
||||
s->func(s->context, &d[comp - 1], 1);
|
||||
stbiw__write1(s, d[comp - 1]);
|
||||
|
||||
switch (comp) {
|
||||
case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
|
||||
|
@ -406,7 +429,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
if (expand_mono)
|
||||
stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
|
||||
else
|
||||
s->func(s->context, d, 1); // monochrome TGA
|
||||
stbiw__write1(s, d[0]); // monochrome TGA
|
||||
break;
|
||||
case 4:
|
||||
if (!write_alpha) {
|
||||
|
@ -422,7 +445,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
break;
|
||||
}
|
||||
if (write_alpha > 0)
|
||||
s->func(s->context, &d[comp - 1], 1);
|
||||
stbiw__write1(s, d[comp - 1]);
|
||||
}
|
||||
|
||||
static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
|
||||
|
@ -447,6 +470,7 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i
|
|||
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
|
||||
stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
|
||||
}
|
||||
stbiw__write_flush(s);
|
||||
s->func(s->context, &zero, scanline_pad);
|
||||
}
|
||||
}
|
||||
|
@ -467,16 +491,27 @@ static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x,
|
|||
|
||||
static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
|
||||
{
|
||||
int pad = (-x*3) & 3;
|
||||
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
|
||||
"11 4 22 4" "4 44 22 444444",
|
||||
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
|
||||
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
|
||||
if (comp != 4) {
|
||||
// write RGB bitmap
|
||||
int pad = (-x*3) & 3;
|
||||
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
|
||||
"11 4 22 4" "4 44 22 444444",
|
||||
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
|
||||
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
|
||||
} else {
|
||||
// RGBA bitmaps need a v4 header
|
||||
// use BI_BITFIELDS mode with 32bpp and alpha mask
|
||||
// (straight BI_RGB with alpha mask doesn't work in most readers)
|
||||
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
|
||||
"11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
|
||||
'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header
|
||||
108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header
|
||||
}
|
||||
}
|
||||
|
||||
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_bmp_core(&s, x, y, comp, data);
|
||||
}
|
||||
|
@ -484,7 +519,7 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_bmp_core(&s, x, y, comp, data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -557,24 +592,25 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v
|
|||
|
||||
if (diff) {
|
||||
unsigned char header = STBIW_UCHAR(len - 1);
|
||||
s->func(s->context, &header, 1);
|
||||
stbiw__write1(s, header);
|
||||
for (k = 0; k < len; ++k) {
|
||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
|
||||
}
|
||||
} else {
|
||||
unsigned char header = STBIW_UCHAR(len - 129);
|
||||
s->func(s->context, &header, 1);
|
||||
stbiw__write1(s, header);
|
||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
stbiw__write_flush(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
||||
}
|
||||
|
@ -582,7 +618,7 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -598,6 +634,8 @@ STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const
|
|||
|
||||
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#ifndef STBI_WRITE_NO_STDIO
|
||||
|
||||
static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
|
||||
{
|
||||
int exponent;
|
||||
|
@ -732,7 +770,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
|
|||
char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
|
||||
s->func(s->context, header, sizeof(header)-1);
|
||||
|
||||
#ifdef __STDC_WANT_SECURE_LIB__
|
||||
#ifdef __STDC_LIB_EXT1__
|
||||
len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
||||
#else
|
||||
len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
||||
|
@ -748,15 +786,14 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
|
|||
|
||||
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||
}
|
||||
|
||||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -774,7 +811,7 @@ STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const
|
|||
|
||||
#ifndef STBIW_ZLIB_COMPRESS
|
||||
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
|
||||
#define stbiw__sbraw(a) ((int *) (a) - 2)
|
||||
#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
|
||||
#define stbiw__sbm(a) stbiw__sbraw(a)[0]
|
||||
#define stbiw__sbn(a) stbiw__sbraw(a)[1]
|
||||
|
||||
|
@ -944,6 +981,23 @@ STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, i
|
|||
(void) stbiw__sbfree(hash_table[i]);
|
||||
STBIW_FREE(hash_table);
|
||||
|
||||
// store uncompressed instead if compression was worse
|
||||
if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
|
||||
stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1
|
||||
for (j = 0; j < data_len;) {
|
||||
int blocklen = data_len - j;
|
||||
if (blocklen > 32767) blocklen = 32767;
|
||||
stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
|
||||
stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
|
||||
stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
|
||||
stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
|
||||
stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
|
||||
memcpy(out+stbiw__sbn(out), data+j, blocklen);
|
||||
stbiw__sbn(out) += blocklen;
|
||||
j += blocklen;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// compute adler32 on input
|
||||
unsigned int s1=1, s2=0;
|
||||
|
@ -1044,13 +1098,13 @@ static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int
|
|||
int type = mymap[filter_type];
|
||||
unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
|
||||
int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
|
||||
|
||||
|
||||
if (type==0) {
|
||||
memcpy(line_buffer, z, width*n);
|
||||
return;
|
||||
}
|
||||
|
||||
// first loop isn't optimized since it's just one pixel
|
||||
// first loop isn't optimized since it's just one pixel
|
||||
for (i = 0; i < n; ++i) {
|
||||
switch (type) {
|
||||
case 1: line_buffer[i] = z[i]; break;
|
||||
|
@ -1271,26 +1325,31 @@ static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
|
|||
bits[0] = val & ((1<<bits[1])-1);
|
||||
}
|
||||
|
||||
static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
|
||||
static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, int du_stride, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
|
||||
const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
|
||||
const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
|
||||
int dataOff, i, diff, end0pos;
|
||||
int dataOff, i, j, n, diff, end0pos, x, y;
|
||||
int DU[64];
|
||||
|
||||
// DCT rows
|
||||
for(dataOff=0; dataOff<64; dataOff+=8) {
|
||||
for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
|
||||
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
|
||||
}
|
||||
// DCT columns
|
||||
for(dataOff=0; dataOff<8; ++dataOff) {
|
||||
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
|
||||
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
|
||||
&CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
|
||||
}
|
||||
// Quantize/descale/zigzag the coefficients
|
||||
for(i=0; i<64; ++i) {
|
||||
float v = CDU[i]*fdtbl[i];
|
||||
// DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
|
||||
// ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
|
||||
DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
|
||||
for(y = 0, j=0; y < 8; ++y) {
|
||||
for(x = 0; x < 8; ++x,++j) {
|
||||
float v;
|
||||
i = y*du_stride+x;
|
||||
v = CDU[i]*fdtbl[j];
|
||||
// DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
|
||||
// ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
|
||||
DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// Encode DC
|
||||
|
@ -1405,10 +1464,10 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
|
|||
37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
|
||||
static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
|
||||
99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
|
||||
static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
|
||||
static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
|
||||
1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
|
||||
|
||||
int row, col, i, k;
|
||||
int row, col, i, k, subsample;
|
||||
float fdtbl_Y[64], fdtbl_UV[64];
|
||||
unsigned char YTable[64], UVTable[64];
|
||||
|
||||
|
@ -1417,6 +1476,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
|
|||
}
|
||||
|
||||
quality = quality ? quality : 90;
|
||||
subsample = quality <= 90 ? 1 : 0;
|
||||
quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
|
||||
quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
|
||||
|
||||
|
@ -1439,7 +1499,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
|
|||
static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
|
||||
static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
|
||||
const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
|
||||
3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
|
||||
3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
|
||||
s->func(s->context, (void*)head0, sizeof(head0));
|
||||
s->func(s->context, (void*)YTable, sizeof(YTable));
|
||||
stbiw__putc(s, 1);
|
||||
|
@ -1462,36 +1522,74 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
|
|||
// Encode 8x8 macroblocks
|
||||
{
|
||||
static const unsigned short fillBits[] = {0x7F, 7};
|
||||
const unsigned char *imageData = (const unsigned char *)data;
|
||||
int DCY=0, DCU=0, DCV=0;
|
||||
int bitBuf=0, bitCnt=0;
|
||||
// comp == 2 is grey+alpha (alpha is ignored)
|
||||
int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
|
||||
const unsigned char *dataR = (const unsigned char *)data;
|
||||
const unsigned char *dataG = dataR + ofsG;
|
||||
const unsigned char *dataB = dataR + ofsB;
|
||||
int x, y, pos;
|
||||
for(y = 0; y < height; y += 8) {
|
||||
for(x = 0; x < width; x += 8) {
|
||||
float YDU[64], UDU[64], VDU[64];
|
||||
for(row = y, pos = 0; row < y+8; ++row) {
|
||||
// row >= height => use last input row
|
||||
int clamped_row = (row < height) ? row : height - 1;
|
||||
int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
|
||||
for(col = x; col < x+8; ++col, ++pos) {
|
||||
float r, g, b;
|
||||
// if col >= width => use pixel from last input column
|
||||
int p = base_p + ((col < width) ? col : (width-1))*comp;
|
||||
if(subsample) {
|
||||
for(y = 0; y < height; y += 16) {
|
||||
for(x = 0; x < width; x += 16) {
|
||||
float Y[256], U[256], V[256];
|
||||
for(row = y, pos = 0; row < y+16; ++row) {
|
||||
// row >= height => use last input row
|
||||
int clamped_row = (row < height) ? row : height - 1;
|
||||
int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
|
||||
for(col = x; col < x+16; ++col, ++pos) {
|
||||
// if col >= width => use pixel from last input column
|
||||
int p = base_p + ((col < width) ? col : (width-1))*comp;
|
||||
float r = dataR[p], g = dataG[p], b = dataB[p];
|
||||
Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
|
||||
U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
|
||||
V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
|
||||
}
|
||||
}
|
||||
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
|
||||
r = imageData[p+0];
|
||||
g = imageData[p+ofsG];
|
||||
b = imageData[p+ofsB];
|
||||
YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
|
||||
UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
|
||||
VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
|
||||
// subsample U,V
|
||||
{
|
||||
float subU[64], subV[64];
|
||||
int yy, xx;
|
||||
for(yy = 0, pos = 0; yy < 8; ++yy) {
|
||||
for(xx = 0; xx < 8; ++xx, ++pos) {
|
||||
int j = yy*32+xx*2;
|
||||
subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
|
||||
subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
|
||||
}
|
||||
}
|
||||
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
|
||||
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(y = 0; y < height; y += 8) {
|
||||
for(x = 0; x < width; x += 8) {
|
||||
float Y[64], U[64], V[64];
|
||||
for(row = y, pos = 0; row < y+8; ++row) {
|
||||
// row >= height => use last input row
|
||||
int clamped_row = (row < height) ? row : height - 1;
|
||||
int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
|
||||
for(col = x; col < x+8; ++col, ++pos) {
|
||||
// if col >= width => use pixel from last input column
|
||||
int p = base_p + ((col < width) ? col : (width-1))*comp;
|
||||
float r = dataR[p], g = dataG[p], b = dataB[p];
|
||||
Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
|
||||
U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
|
||||
V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
|
||||
}
|
||||
}
|
||||
|
||||
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
|
||||
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
|
||||
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
|
||||
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1508,7 +1606,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
|
|||
|
||||
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
|
||||
}
|
||||
|
@ -1517,7 +1615,7 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -1530,10 +1628,17 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
|
|||
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
/* Revision history
|
||||
1.16 (2021-07-11)
|
||||
make Deflate code emit uncompressed blocks when it would otherwise expand
|
||||
support writing BMPs with alpha channel
|
||||
1.15 (2020-07-13) unknown
|
||||
1.14 (2020-02-02) updated JPEG writer to downsample chroma channels
|
||||
1.13
|
||||
1.12
|
||||
1.11 (2019-08-11)
|
||||
|
||||
|
||||
1.10 (2019-02-07)
|
||||
support utf8 filenames in Windows; fix warnings and platform ifdefs
|
||||
support utf8 filenames in Windows; fix warnings and platform ifdefs
|
||||
1.09 (2018-02-11)
|
||||
fix typo in zlib quality API, improve STB_I_W_STATIC in C++
|
||||
1.08 (2018-01-29)
|
||||
|
@ -1564,7 +1669,7 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
|
|||
add HDR output
|
||||
fix monochrome BMP
|
||||
0.95 (2014-08-17)
|
||||
add monochrome TGA output
|
||||
add monochrome TGA output
|
||||
0.94 (2014-05-31)
|
||||
rename private functions to avoid conflicts with stb_image.h
|
||||
0.93 (2014-05-27)
|
||||
|
@ -1582,38 +1687,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
|
|||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue