--- stb/stb_image.h 2018-11-20 14:06:26.446637000 -0800 +++ stb_image.h 2018-11-20 14:10:10.830961000 -0800 @@ -420,14 +420,14 @@ STBIDEF void stbi_image_free (void *retval_from_stbi_load); // get image dimensions & components without fully decoding -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, float *gamma); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, float *gamma); STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); #ifndef STBI_NO_STDIO -STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp, float *gamma); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp, float *gamma); STBIDEF int stbi_is_16_bit (char const *filename); STBIDEF int stbi_is_16_bit_from_file(FILE *f); #endif @@ -792,7 +792,7 @@ #ifndef STBI_NO_PNG static int stbi__png_test(stbi__context *s); static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp, float *gamma); static int stbi__png_is16(stbi__context *s); #endif @@ -4290,6 +4290,7 @@ stbi__context *s; stbi_uc *idata, *expanded, *out; int depth; + float gamma = 0; } stbi__png; @@ -4818,6 +4819,13 @@ break; } + case STBI__PNG_TYPE('g','A','M','A'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (4 != c.length) return stbi__err("invalid gAMA","Corrupt PNG"); + z->gamma = stbi__get32be(s) / 100000.0f; + break; + } + case STBI__PNG_TYPE('I','D','A','T'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); @@ -4900,6 +4908,38 @@ } } +// XXX PIXAR: +// Helper functions for associating alpha values with colors +static void pxr__associate_alpha(unsigned char *data, int x, int y, int n) +{ + STBI_ASSERT(n == 4); + stbi__uint32 i, pixel_count = x * y; + for (i=0; i < pixel_count; ++i) { + float alpha = (float)data[3] / 255.0f; + if (alpha < 1.0) { + data[0] = data[0] * alpha + 0.5; + data[1] = data[1] * alpha + 0.5; + data[2] = data[2] * alpha + 0.5; + } + data += 4; + } +} + +static void pxr__associate_alpha16(stbi__uint16 *data, int x, int y, int n) +{ + STBI_ASSERT(n == 4); + stbi__uint32 i, pixel_count = x * y; + for (i=0; i < pixel_count; ++i) { + float alpha = (float)data[3] / 65535.0f; + if (alpha < 1.0) { + data[0] = data[0] * alpha + 0.5; + data[1] = data[1] * alpha + 0.5; + data[2] = data[2] * alpha + 0.5; + } + data += 4; + } +} + static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) { void *result=NULL; @@ -4922,6 +4962,15 @@ *x = p->s->img_x; *y = p->s->img_y; if (n) *n = p->s->img_n; + + // XXX PIXAR: + // Associate alpha to accommodate client code. + if (p->s->img_n == 4) { + if (ri->bits_per_channel == 8) + pxr__associate_alpha((unsigned char *) result, *x, *y, p->s->img_n); + else + pxr__associate_alpha16((stbi__uint16 *) result, *x, *y, p->s->img_n); + } } STBI_FREE(p->out); p->out = NULL; STBI_FREE(p->expanded); p->expanded = NULL; @@ -4945,7 +4994,7 @@ return r; } -static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp, float *gamma) { if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { stbi__rewind( p->s ); @@ -4954,21 +5003,22 @@ if (x) *x = p->s->img_x; if (y) *y = p->s->img_y; if (comp) *comp = p->s->img_n; + if (gamma) *gamma = p->gamma; return 1; } -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp, float *gamma) { stbi__png p; p.s = s; - return stbi__png_info_raw(&p, x, y, comp); + return stbi__png_info_raw(&p, x, y, comp, gamma); } static int stbi__png_is16(stbi__context *s) { stbi__png p; p.s = s; - if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + if (!stbi__png_info_raw(&p, NULL, NULL, NULL, NULL)) return 0; if (p.depth != 16) { stbi__rewind(p.s); @@ -7107,14 +7157,14 @@ } #endif -static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp, float *gamma) { #ifndef STBI_NO_JPEG if (stbi__jpeg_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PNG - if (stbi__png_info(s, x, y, comp)) return 1; + if (stbi__png_info(s, x, y, comp, gamma)) return 1; #endif #ifndef STBI_NO_GIF @@ -7163,23 +7213,23 @@ } #ifndef STBI_NO_STDIO -STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp, float *gamma) { FILE *f = stbi__fopen(filename, "rb"); int result; if (!f) return stbi__err("can't fopen", "Unable to open file"); - result = stbi_info_from_file(f, x, y, comp); + result = stbi_info_from_file(f, x, y, comp, gamma); fclose(f); return result; } -STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp, float *gamma) { int r; stbi__context s; long pos = ftell(f); stbi__start_file(&s, f); - r = stbi__info_main(&s,x,y,comp); + r = stbi__info_main(&s,x,y,comp, gamma); fseek(f,pos,SEEK_SET); return r; } @@ -7206,18 +7256,18 @@ } #endif // !STBI_NO_STDIO -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, float *gamma) { stbi__context s; stbi__start_mem(&s,buffer,len); - return stbi__info_main(&s,x,y,comp); + return stbi__info_main(&s,x,y,comp, gamma); } -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp, float *gamma) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); - return stbi__info_main(&s,x,y,comp); + return stbi__info_main(&s,x,y,comp, gamma); } STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)