| 7332 | } |
| 7333 | |
| 7334 | static stbi_uc* stbi__process_gif_raster(stbi__context* s, stbi__gif* g) { |
| 7335 | stbi_uc lzw_cs; |
| 7336 | stbi__int32 len, init_code; |
| 7337 | stbi__uint32 first; |
| 7338 | stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; |
| 7339 | stbi__gif_lzw* p; |
| 7340 | |
| 7341 | lzw_cs = stbi__get8(s); |
| 7342 | if (lzw_cs > 12) |
| 7343 | return NULL; |
| 7344 | clear = 1 << lzw_cs; |
| 7345 | first = 1; |
| 7346 | codesize = lzw_cs + 1; |
| 7347 | codemask = (1 << codesize) - 1; |
| 7348 | bits = 0; |
| 7349 | valid_bits = 0; |
| 7350 | for (init_code = 0; init_code < clear; init_code++) { |
| 7351 | g->codes[init_code].prefix = -1; |
| 7352 | g->codes[init_code].first = (stbi_uc)init_code; |
| 7353 | g->codes[init_code].suffix = (stbi_uc)init_code; |
| 7354 | } |
| 7355 | |
| 7356 | // support no starting clear code |
| 7357 | avail = clear + 2; |
| 7358 | oldcode = -1; |
| 7359 | |
| 7360 | len = 0; |
| 7361 | for (;;) { |
| 7362 | if (valid_bits < codesize) { |
| 7363 | if (len == 0) { |
| 7364 | len = stbi__get8(s); // start new block |
| 7365 | if (len == 0) |
| 7366 | return g->out; |
| 7367 | } |
| 7368 | --len; |
| 7369 | bits |= (stbi__int32)stbi__get8(s) << valid_bits; |
| 7370 | valid_bits += 8; |
| 7371 | } else { |
| 7372 | stbi__int32 code = bits & codemask; |
| 7373 | bits >>= codesize; |
| 7374 | valid_bits -= codesize; |
| 7375 | // @OPTIMIZE: is there some way we can accelerate the non-clear path? |
| 7376 | if (code == clear) { // clear code |
| 7377 | codesize = lzw_cs + 1; |
| 7378 | codemask = (1 << codesize) - 1; |
| 7379 | avail = clear + 2; |
| 7380 | oldcode = -1; |
| 7381 | first = 0; |
| 7382 | } else if (code == clear + 1) { // end of stream code |
| 7383 | stbi__skip(s, len); |
| 7384 | while ((len = stbi__get8(s)) > 0) |
| 7385 | stbi__skip(s, len); |
| 7386 | return g->out; |
| 7387 | } else if (code <= avail) { |
| 7388 | if (first) { |
| 7389 | return stbi__errpuc("no clear code", "Corrupt GIF"); |
| 7390 | } |
| 7391 |
no test coverage detected