diff --git a/src/stb_image.h b/src/stb_image.h index c28b5286..ce87646d 100644 --- a/src/stb_image.h +++ b/src/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.09 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -146,6 +146,12 @@ Latest revision history: + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) partial animated GIF support @@ -166,10 +172,6 @@ STBI_MALLOC,STBI_REALLOC,STBI_FREE STBI_NO_*, STBI_ONLY_* GIF bugfix - 1.48 (2014-12-14) fix incorrectly-named assert() - 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted) - optimize PNG - fix bug in interlaced PNG with user-specified channel count See end of file for full revision history. @@ -200,17 +202,17 @@ Janez Zemva John Bartholomew Michal Cichon svdijk@github Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github - Aruelien Pocheville Thibault Reuille Cass Everitt - Ryamond Barbiero Paul Du Bois Engin Manap + Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan + Ryamond Barbiero Paul Du Bois Engin Manap snagar@github + Michaelangel007@github Oriol Ferrer Mesia socks-the-fox Blazej Dariusz Roszkowski - Michaelangel007@github LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. */ @@ -679,7 +681,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_NO_SIMD #endif -#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET) +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) #define STBI_SSE2 #include @@ -1513,6 +1515,7 @@ typedef struct int succ_high; int succ_low; int eob_run; + int rgb; int scan_n, order[4]; int restart_interval, todo; @@ -2724,11 +2727,17 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + z->rgb = 0; for (i=0; i < s->img_n; ++i) { + static unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); if (z->img_comp[i].id != i+1) // JFIF requires - if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! - return stbi__err("bad component ID","Corrupt JPEG"); + if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files! + // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format) + if (z->img_comp[i].id != rgb[i]) + return stbi__err("bad component ID","Corrupt JPEG"); + ++z->rgb; + } q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); @@ -3390,7 +3399,17 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (n >= 3) { stbi_uc *y = coutput[0]; if (z->s->img_n == 3) { - z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + if (z->rgb == 3) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } } else for (i=0; i < z->s->img_x; ++i) { out[0] = out[1] = out[2] = y[i]; @@ -3415,10 +3434,13 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) { - stbi__jpeg j; - j.s = s; - stbi__setup_jpeg(&j); - return load_jpeg_image(&j, x,y,comp,req_comp); + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; } static int stbi__jpeg_test(stbi__context *s) @@ -3446,9 +3468,12 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) { - stbi__jpeg j; - j.s = s; - return stbi__jpeg_info_raw(&j, x, y, comp); + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; } #endif @@ -3629,6 +3654,7 @@ static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room while (cur + n > limit) limit *= 2; q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); if (q == NULL) return stbi__err("outofmem", "Out of memory"); z->zout_start = q; z->zout = q + cur; @@ -3738,7 +3764,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) return 1; } -static int stbi__parse_uncomperssed_block(stbi__zbuf *a) +static int stbi__parse_uncompressed_block(stbi__zbuf *a) { stbi_uc header[4]; int len,nlen,k; @@ -3804,7 +3830,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) final = stbi__zreceive(a,1); type = stbi__zreceive(a,2); if (type == 0) { - if (!stbi__parse_uncomperssed_block(a)) return 0; + if (!stbi__parse_uncompressed_block(a)) return 0; } else if (type == 3) { return 0; } else { @@ -3946,6 +3972,7 @@ typedef struct { stbi__context *s; stbi_uc *idata, *expanded, *out; + int depth; } stbi__png; @@ -3985,14 +4012,19 @@ static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x0 // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { + int bytes = (depth == 16? 2 : 1); stbi__context *s = a->s; - stbi__uint32 i,j,stride = x*out_n; + stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 img_len, img_width_bytes; int k; int img_n = s->img_n; // copy it into a local for later + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into + a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); @@ -4007,8 +4039,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r stbi_uc *cur = a->out + stride*j; stbi_uc *prior = cur - stride; int filter = *raw++; - int filter_bytes = img_n; - int width = x; + if (filter > 4) return stbi__err("invalid filter","Corrupt PNG"); @@ -4041,6 +4072,14 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r raw += img_n; 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; @@ -4049,7 +4088,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r // this is a little gross, so that we don't switch per-pixel or per-component if (depth < 8 || img_n == out_n) { - int nk = (width - 1)*img_n; + int nk = (width - 1)*filter_bytes; #define CASE(f) \ case f: \ for (k=0; k < nk; ++k) @@ -4069,18 +4108,27 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r STBI_ASSERT(img_n+1 == out_n); #define CASE(f) \ case f: \ - for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ - for (k=0; k < img_n; ++k) + 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) { CASE(STBI__F_none) cur[k] = raw[k]; break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break; CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break; } #undef CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } } } @@ -4156,6 +4204,17 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r } } } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } } return 1; @@ -4228,6 +4287,31 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) return 1; } +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) { stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; @@ -4265,6 +4349,26 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int return 1; } +static int stbi__reduce_png(stbi__png *p) +{ + int i; + int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n; + stbi_uc *reduced; + stbi__uint16 *orig = (stbi__uint16*)p->out; + + if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data + + reduced = (stbi_uc *)stbi__malloc(img_len); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling + + p->out = reduced; + STBI_FREE(orig); + + return 1; +} + static int stbi__unpremultiply_on_load = 0; static int stbi__de_iphone_flag = 0; @@ -4326,8 +4430,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { stbi_uc palette[1024], pal_img_n=0; stbi_uc has_trans=0, tc[3]; + stbi__uint16 tc16[3]; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; - int first=1,k,interlace=0, color=0, depth=0, is_iphone=0; + int first=1,k,interlace=0, color=0, is_iphone=0; stbi__context *s = z->s; z->expanded = NULL; @@ -4352,8 +4457,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); - depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); @@ -4401,8 +4507,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; - for (k=0; k < s->img_n; ++k) - tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } } break; } @@ -4418,6 +4527,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); z->idata = p; } @@ -4432,7 +4542,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (scan != STBI__SCAN_load) return 1; if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); // initial guess for decoded data size to avoid unnecessary reallocs - bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); if (z->expanded == NULL) return 0; // zlib should set error @@ -4441,9 +4551,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) s->img_out_n = s->img_n+1; else s->img_out_n = s->img_n; - if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0; - if (has_trans) - if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) stbi__de_iphone(z); if (pal_img_n) { @@ -4485,6 +4600,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req unsigned char *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth == 16) { + if (!stbi__reduce_png(p)) { + return result; + } + } result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { @@ -4494,7 +4614,7 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req } *x = p->s->img_x; *y = p->s->img_y; - if (n) *n = p->s->img_out_n; + if (n) *n = p->s->img_n; } STBI_FREE(p->out); p->out = NULL; STBI_FREE(p->expanded); p->expanded = NULL; @@ -4619,6 +4739,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) stbi__get16le(s); // discard reserved info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { @@ -4647,7 +4768,6 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) stbi__get32le(s); } if (info->bpp == 16 || info->bpp == 32) { - info->mr = info->mg = info->mb = 0; if (compress == 0) { if (info->bpp == 32) { info->mr = 0xffu << 16; @@ -5342,6 +5462,21 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int } } + if (channelCount >= 4) { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + // remove weird white matte from PSD + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + if (req_comp && req_comp != 4) { out = stbi__convert_format(out, 4, req_comp, w, h); if (out == NULL) return out; // stbi__convert_format frees input on failure @@ -5654,13 +5789,15 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) { - stbi__gif g; - if (!stbi__gif_header(s, &g, comp, 1)) { + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); stbi__rewind( s ); return 0; } - if (x) *x = g.w; - if (y) *y = g.h; + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); return 1; } @@ -5913,20 +6050,20 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi_uc *u = 0; - stbi__gif g; - memset(&g, 0, sizeof(g)); + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + memset(g, 0, sizeof(*g)); - u = stbi__gif_load_next(s, &g, comp, req_comp); + u = stbi__gif_load_next(s, g, comp, req_comp); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { - *x = g.w; - *y = g.h; + *x = g->w; + *y = g->h; if (req_comp && req_comp != 4) - u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + u = stbi__convert_format(u, 4, req_comp, g->w, g->h); } - else if (g.out) - STBI_FREE(g.out); - + else if (g->out) + STBI_FREE(g->out); + STBI_FREE(g); return u; } @@ -6464,6 +6601,14 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED 2.09 (2016-01-16) allow comments in PNM files 16-bit-per-pixel TGA (not bit-per-component) info() for TGA could break due to .hdr handling diff --git a/src/stb_image_resize.h b/src/stb_image_resize.h index 4ce7ddbf..4cabe540 100644 --- a/src/stb_image_resize.h +++ b/src/stb_image_resize.h @@ -1,4 +1,4 @@ -/* stb_image_resize - v0.90 - public domain image resizing +/* stb_image_resize - v0.91 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb @@ -156,13 +156,14 @@ Sean Barrett: API design, optimizations REVISIONS + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions 0.90 (2014-09-17) first released version LICENSE - This software is in the public domain. Where that dedication is not - recognized, you are granted a perpetual, irrevocable license to copy, - distribute, and modify this file as you see fit. + This software is dual-licensed to the public domain and under the following + license: you are granted a perpetual, irrevocable license to copy, modify, + publish, and distribute this file as you see fit. TODO Don't decode all of the image data when only processing a partial tile @@ -383,15 +384,6 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int #define STBIR_ASSERT(x) assert(x) #endif -#ifdef STBIR_DEBUG -#define STBIR__DEBUG_ASSERT STBIR_ASSERT -#else -#define STBIR__DEBUG_ASSERT -#endif - -// If you hit this it means I haven't done it yet. -#define STBIR__UNIMPLEMENTED(x) STBIR_ASSERT(!(x)) - // For memset #include @@ -758,7 +750,7 @@ static float stbir__filter_trapezoid(float x, float scale) { float halfscale = scale / 2; float t = 0.5f + halfscale; - STBIR__DEBUG_ASSERT(scale <= 1); + STBIR_ASSERT(scale <= 1); x = (float)fabs(x); @@ -776,7 +768,7 @@ static float stbir__filter_trapezoid(float x, float scale) static float stbir__support_trapezoid(float scale) { - STBIR__DEBUG_ASSERT(scale <= 1); + STBIR_ASSERT(scale <= 1); return 0.5f + scale / 2; } @@ -990,7 +982,7 @@ static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) return n; // NOTREACHED default: - STBIR__UNIMPLEMENTED("Unimplemented edge type"); + STBIR_ASSERT(!"Unimplemented edge type"); return 0; } } @@ -1039,12 +1031,12 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi float total_filter = 0; float filter_scale; - STBIR__DEBUG_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. contributor->n0 = in_first_pixel; contributor->n1 = in_last_pixel; - STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0); + STBIR_ASSERT(contributor->n1 >= contributor->n0); for (i = 0; i <= in_last_pixel - in_first_pixel; i++) { @@ -1062,10 +1054,10 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi total_filter += coefficient_group[i]; } - STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); - STBIR__DEBUG_ASSERT(total_filter > 0.9); - STBIR__DEBUG_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. // Make sure the sum of all coefficients is 1. filter_scale = 1 / total_filter; @@ -1087,12 +1079,12 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st { int i; - STBIR__DEBUG_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. contributor->n0 = out_first_pixel; contributor->n1 = out_last_pixel; - STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0); + STBIR_ASSERT(contributor->n1 >= contributor->n0); for (i = 0; i <= out_last_pixel - out_first_pixel; i++) { @@ -1101,7 +1093,7 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; } - STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); for (i = out_last_pixel - out_first_pixel; i >= 0; i--) { @@ -1136,8 +1128,8 @@ static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, st break; } - STBIR__DEBUG_ASSERT(total > 0.9f); - STBIR__DEBUG_ASSERT(total < 1.1f); + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); scale = 1 / total; @@ -1364,7 +1356,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) break; default: - STBIR__UNIMPLEMENTED("Unknown type/colorspace/channels combination."); + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); break; } @@ -1425,7 +1417,7 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) else { ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width; - STBIR__DEBUG_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); } ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); @@ -1457,11 +1449,11 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, int coefficient_group = coefficient_width * x; int coefficient_counter = 0; - STBIR__DEBUG_ASSERT(n1 >= n0); - STBIR__DEBUG_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); - STBIR__DEBUG_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); - STBIR__DEBUG_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); - STBIR__DEBUG_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); switch (channels) { case 1: @@ -1469,7 +1461,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 1; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; } break; @@ -1478,7 +1470,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 2; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; } @@ -1488,7 +1480,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 3; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1499,7 +1491,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 4; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1512,7 +1504,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, int in_pixel_index = k * channels; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; int c; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); for (c = 0; c < channels; c++) output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; } @@ -1535,7 +1527,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; int max_x = input_w + filter_pixel_margin * 2; - STBIR__DEBUG_ASSERT(!stbir__use_width_upsampling(stbir_info)); + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); switch (channels) { case 1: @@ -1553,7 +1545,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 1; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; } } @@ -1574,7 +1566,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 2; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; } @@ -1596,7 +1588,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 3; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1619,7 +1611,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 4; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1644,7 +1636,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n int c; int out_pixel_index = k * channels; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); for (c = 0; c < channels; c++) output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; } @@ -1856,7 +1848,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void break; default: - STBIR__UNIMPLEMENTED("Unknown type/colorspace/channels combination."); + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); break; } } @@ -1893,7 +1885,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in output_row_start = n * stbir_info->output_stride_bytes; - STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); memset(encode_buffer, 0, output_w * sizeof(float) * channels); @@ -2003,7 +1995,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, n0 = vertical_contributors[contributor].n0; n1 = vertical_contributors[contributor].n1; - STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); for (k = n0; k <= n1; k++) { @@ -2068,7 +2060,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) float scale_ratio = stbir_info->vertical_scale; float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; - STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); for (y = 0; y < stbir_info->output_h; y++) { @@ -2077,7 +2069,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); - STBIR__DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width); if (stbir_info->ring_buffer_begin_index >= 0) { @@ -2169,7 +2161,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) int pixel_margin = stbir_info->vertical_filter_pixel_margin; int max_y = stbir_info->input_h + pixel_margin; - STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); for (y = -pixel_margin; y < max_y; y++) { @@ -2178,7 +2170,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); - STBIR__DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width); if (out_last_scanline < 0 || out_first_scanline >= output_h) continue; @@ -2229,8 +2221,8 @@ static void stbir__calculate_transform(stbir__info *info, float s0, float t0, fl info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); - info->horizontal_shift = s0 * info->input_w / (s1 - s0); - info->vertical_shift = t0 * info->input_h / (t1 - t0); + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); } } @@ -2380,7 +2372,7 @@ static int stbir__resize_allocated(stbir__info *info, info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); - STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); } else { @@ -2388,7 +2380,7 @@ static int stbir__resize_allocated(stbir__info *info, info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); info->encode_buffer = NULL; - STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); } #undef STBIR__NEXT_MEMPTR @@ -2409,10 +2401,10 @@ static int stbir__resize_allocated(stbir__info *info, STBIR_PROGRESS_REPORT(1); #ifdef STBIR_DEBUG_OVERWRITE_TEST - STBIR__DEBUG_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); - STBIR__DEBUG_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); - STBIR__DEBUG_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); - STBIR__DEBUG_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); #endif return 1; diff --git a/src/stb_image_write.h b/src/stb_image_write.h index 98fa4103..4319c0de 100644 --- a/src/stb_image_write.h +++ b/src/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.01 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -102,12 +102,13 @@ CREDITS: Sergio Gonzalez Jonas Karlsson Filip Wasil + Thatcher Ulrich LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. */ @@ -736,7 +737,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l unsigned int bitbuf=0; int i,j, bitcount=0; unsigned char *out = NULL; - unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack! + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); if (quality < 5) quality = 5; stbiw__sbpush(out, 0x78); // DEFLATE 32K window @@ -808,6 +809,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l for (i=0; i < stbiw__ZHASH; ++i) (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); { // compute adler32 on input @@ -1015,6 +1017,8 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack 1.01 (2016-01-16) STBIW_REALLOC_SIZED: support allocators with no realloc support avoid race-condition in crc initialization diff --git a/src/stb_rect_pack.h b/src/stb_rect_pack.h index 63a5b159..bd1cfc60 100644 --- a/src/stb_rect_pack.h +++ b/src/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.06 - public domain - rectangle packing +// stb_rect_pack.h - v0.08 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -28,14 +28,22 @@ // Minor features // Martins Mozeiko // Bugfixes / warning fixes -// [your name could be here] +// Jeremy Jaussaud // // Version history: // +// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) +// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort // 0.05: added STBRP_ASSERT to allow replacing assert // 0.04: fixed minor bug in STBRP_LARGE_RECTS support // 0.01: initial release +// +// LICENSE +// +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. ////////////////////////////////////////////////////////////////////////////// // @@ -541,12 +549,16 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); for (i=0; i < num_rects; ++i) { - stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); - if (fr.prev_link) { - rects[i].x = (stbrp_coord) fr.x; - rects[i].y = (stbrp_coord) fr.y; + if (rects[i].w == 0 || rects[i].h == 0) { + rects[i].x = rects[i].y = 0; // empty rect needs no space } else { - rects[i].x = rects[i].y = STBRP__MAXVAL; + stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); + if (fr.prev_link) { + rects[i].x = (stbrp_coord) fr.x; + rects[i].y = (stbrp_coord) fr.y; + } else { + rects[i].x = rects[i].y = STBRP__MAXVAL; + } } } diff --git a/src/stb_truetype.h b/src/stb_truetype.h index bfb1841f..d360d609 100644 --- a/src/stb_truetype.h +++ b/src/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.09 - public domain +// stb_truetype.h - v1.11 - public domain // authored from 2009-2015 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -21,6 +21,10 @@ // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering // +// Misc other: +// Ryan Gordon +// Simon Glass +// // Bug/warning reports/fixes: // "Zer" on mollyrocket (with fix) // Cass Everitt @@ -45,11 +49,10 @@ // Thomas Fields // Derek Vinyard // -// Misc other: -// Ryan Gordon -// // VERSION HISTORY // +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; @@ -68,9 +71,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // // USAGE // @@ -406,6 +409,11 @@ int main(int arg, char **argv) #define STBTT_sqrt(x) sqrt(x) #endif + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h #ifndef STBTT_malloc #include @@ -629,7 +637,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // The following structure is defined publically so you can declare one on // the stack or as a global or etc, but you should treat it as opaque. -typedef struct stbtt_fontinfo +struct stbtt_fontinfo { void * userdata; unsigned char * data; // pointer to .ttf file @@ -640,7 +648,7 @@ typedef struct stbtt_fontinfo int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph -} stbtt_fontinfo; +}; STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); // Given an offset into the file that defines a font, this function builds @@ -942,6 +950,12 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define STBTT_RASTERIZER_VERSION 2 #endif +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file @@ -1993,7 +2007,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, } y_crossing += dy * (x2 - (x1+1)); - STBTT_assert(fabs(area) <= 1.01f); + STBTT_assert(STBTT_fabs(area) <= 1.01f); scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); @@ -2071,6 +2085,8 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int y,j=0, i; float scanline_data[129], *scanline, *scanline2; + STBTT__NOTUSED(vsubsample); + if (result->w > 64) scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); else @@ -2129,7 +2145,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int m; sum += scanline2[i]; k = scanline[i] + sum; - k = (float) fabs(k)*255 + 0.5f; + k = (float) STBTT_fabs(k)*255 + 0.5f; m = (int) k; if (m > 255) m = 255; result->pixels[j*result->stride + i] = (unsigned char) m; @@ -2430,7 +2446,10 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info if (scale_x == 0) scale_x = scale_y; if (scale_y == 0) { - if (scale_x == 0) return NULL; + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } scale_y = scale_x; } @@ -2586,11 +2605,6 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int // #ifndef STB_RECT_PACK_VERSION -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif typedef int stbrp_coord; @@ -3205,6 +3219,10 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // FULL VERSION HISTORY // +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; diff --git a/src/stb_vorbis.c b/src/stb_vorbis.c index 0510edc7..07d79318 100644 --- a/src/stb_vorbis.c +++ b/src/stb_vorbis.c @@ -168,6 +168,9 @@ #include #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) #include +#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) +#include +#endif #endif #else // STB_VORBIS_NO_CRT #define NULL 0 @@ -1484,85 +1487,6 @@ static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **out return TRUE; } -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK -static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **outputs, int *c_inter_p, int *p_inter_p, int len, int total_decode) -{ - int c_inter = *c_inter_p; - int p_inter = *p_inter_p; - int i,z, effective = c->dimensions; - - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); - - while (total_decode > 0) { - float last = CODEBOOK_ELEMENT_BASE(c); - DECODE_VQ(z,f,c); - - if (z < 0) { - if (!f->bytes_in_seg) - if (f->last_seg) return FALSE; - return error(f, VORBIS_invalid_stream); - } - - // if this will take us off the end of the buffers, stop short! - // we check by computing the length of the virtual interleaved - // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), - // and the length we'll be using (effective) - if (c_inter + p_inter*2 + effective > len * 2) { - effective = len*2 - (p_inter*2 - c_inter); - } - - { - z *= c->dimensions; - if (c->sequence_p) { - // haven't optimized this case because I don't have any examples - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == 2) { c_inter = 0; ++p_inter; } - last = val; - } - } else { - i=0; - if (c_inter == 1 && i < effective) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - c_inter = 0; ++p_inter; - ++i; - } - { - float *z0 = outputs[0]; - float *z1 = outputs[1]; - for (; i+1 < effective;) { - float v0 = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - float v1 = CODEBOOK_ELEMENT_FAST(c,z+i+1) + last; - if (z0) - z0[p_inter] += v0; - if (z1) - z1[p_inter] += v1; - ++p_inter; - i += 2; - } - } - if (i < effective) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == 2) { c_inter = 0; ++p_inter; } - } - } - } - - total_decode -= effective; - } - *c_inter_p = c_inter; - *p_inter_p = p_inter; - return TRUE; -} -#endif - static int predict_point(int x, int x0, int x1, int y0, int y1) { int dy = y1 - y0; @@ -1941,6 +1865,11 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } done: CHECK(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + temp_free(f,part_classdata); + #else + temp_free(f,classifications); + #endif temp_alloc_restore(f,temp_alloc_point); } @@ -2586,6 +2515,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) } } + temp_free(f,buf2); temp_alloc_restore(f,save_point); } @@ -3499,7 +3429,6 @@ static int start_decoder(vorb *f) } } } - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); c->lookup_type = 2; } else @@ -3515,11 +3444,11 @@ static int start_decoder(vorb *f) if (c->sequence_p) last = val; } - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); } #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK skip:; #endif + setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); CHECK(f); } @@ -4045,7 +3974,7 @@ int stb_vorbis_decode_frame_pushdata( while (get8_packet(f) != EOP) if (f->eof) break; *samples = 0; - return f->stream - data; + return (int) (f->stream - data); } if (error == VORBIS_continued_packet_flag_invalid) { if (f->previous_length == 0) { @@ -4055,7 +3984,7 @@ int stb_vorbis_decode_frame_pushdata( while (get8_packet(f) != EOP) if (f->eof) break; *samples = 0; - return f->stream - data; + return (int) (f->stream - data); } } // if we get an error while parsing, what to do? @@ -4075,7 +4004,7 @@ int stb_vorbis_decode_frame_pushdata( if (channels) *channels = f->channels; *samples = len; *output = f->outputs; - return f->stream - data; + return (int) (f->stream - data); } stb_vorbis *stb_vorbis_open_pushdata( @@ -4098,7 +4027,7 @@ stb_vorbis *stb_vorbis_open_pushdata( f = vorbis_alloc(&p); if (f) { *f = p; - *data_used = f->stream - data; + *data_used = (int) (f->stream - data); *error = 0; return f; } else { @@ -4113,9 +4042,9 @@ unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) #ifndef STB_VORBIS_NO_PUSHDATA_API if (f->push_mode) return 0; #endif - if (USE_MEMORY(f)) return f->stream - f->stream_start; + if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start); #ifndef STB_VORBIS_NO_STDIO - return ftell(f->f) - f->f_start; + return (unsigned int) (ftell(f->f) - f->f_start); #endif } @@ -4611,7 +4540,7 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er stb_vorbis *f, p; vorbis_init(&p, alloc); p.f = file; - p.f_start = ftell(file); + p.f_start = (uint32) ftell(file); p.stream_len = length; p.close_on_free = close_on_free; if (start_decoder(&p)) { @@ -4630,9 +4559,9 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) { unsigned int len, start; - start = ftell(file); + start = (unsigned int) ftell(file); fseek(file, 0, SEEK_END); - len = ftell(file) - start; + len = (unsigned int) (ftell(file) - start); fseek(file, start, SEEK_SET); return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); } @@ -5027,6 +4956,9 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version + 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; + avoid discarding last frame of audio data 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API some more crash fixes when out of memory or with corrupt files 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) diff --git a/src/stb_vorbis.h b/src/stb_vorbis.h index bd318972..624ce4bc 100644 --- a/src/stb_vorbis.h +++ b/src/stb_vorbis.h @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.07 - public domain +// Ogg Vorbis audio decoder - v1.09 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -9,9 +9,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // // No warranty for any purpose is expressed or implied by the author (nor // by RAD Game Tools). Report bugs and send enhancements to the author. @@ -31,11 +31,14 @@ // Terje Mathisen Niklas Frykholm Andy Hill // Casey Muratori John Bolton Gargaj // Laurent Gomila Marc LeBlanc Ronny Chevalier -// Bernhard Wodo Evan Balster "alxprd"@github +// Bernhard Wodo Evan Balster alxprd@github // Tom Beaumont Ingo Leitgeb Nicolas Guillemot -// Phillip Bennefall Rohit +// Phillip Bennefall Rohit Thiago Goulart +// manxorist@github saga musix // // Partial history: +// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version +// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame // 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const // 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) // some crash fixes when out of memory or with corrupt files @@ -72,11 +75,6 @@ #include "utils.h" // Android fopen function map #endif -// RaySan: Added for Linux -#ifdef __linux - #include -#endif - #ifdef __cplusplus extern "C" { #endif