From 24fa8161166327af9f9d35cabf520d69d233a04e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:31:06 -0700 Subject: [PATCH] merge https://github.com/nothings/stb/pull/427 but I messed up the merge so you don't get the automatic info you normally do --- stb_image.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/stb_image.h b/stb_image.h index 2a40cd7..2a1d264 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2628,7 +2628,7 @@ static void stbi__jpeg_reset(stbi__jpeg *j) j->code_bits = 0; j->code_buffer = 0; j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; j->marker = STBI__MARKER_none; j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; j->eob_run = 0; @@ -2959,7 +2959,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires c = stbi__get8(s); - if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); s->img_n = c; for (i=0; i < c; ++i) { z->img_comp[i].data = NULL; @@ -2972,7 +2972,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) 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 == rgb[i]) + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) ++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"); @@ -3516,6 +3516,13 @@ typedef struct int ypos; // which pre-expansion row we're on } stbi__resample; +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { int n, decode_n, is_rgb; @@ -3528,7 +3535,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } // determine actual number of components to generate - n = req_comp ? req_comp : z->s->img_n; + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); @@ -3603,6 +3610,28 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } else { z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], k); + out[1] = stbi__blinn_8x8(coutput[1][i], k); + out[2] = stbi__blinn_8x8(coutput[2][i], k); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], k); + out[1] = stbi__blinn_8x8(255 - out[1], k); + out[2] = stbi__blinn_8x8(255 - out[2], k); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + 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]; @@ -3620,6 +3649,22 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp out[1] = 255; } } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], k); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], k); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], k); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } } else { stbi_uc *y = coutput[0]; if (n == 1) @@ -3632,7 +3677,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp stbi__cleanup_jpeg(z); *out_x = z->s->img_x; *out_y = z->s->img_y; - if (comp) *comp = z->s->img_n; // report original components, not output + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output return output; } } @@ -3669,7 +3714,7 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) } if (x) *x = j->s->img_x; if (y) *y = j->s->img_y; - if (comp) *comp = j->s->img_n; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; return 1; }