public static int stbi_zlib_decode_noheader_buffer(sbyte *obuffer, int olen, sbyte *ibuffer, int ilen) { var a = new stbi__zbuf(); a.zbuffer = (byte *)ibuffer; a.zbuffer_end = (byte *)ibuffer + ilen; if (stbi__do_zlib(&a, obuffer, olen, 0, 0) != 0) { return((int)(a.zout - a.zout_start)); } return(-1); }
public static sbyte *stbi_zlib_decode_noheader_malloc(sbyte *buffer, int len, int *outlen) { var a = new stbi__zbuf(); var p = (sbyte *)stbi__malloc((ulong)16384); if (p == null) { return(null); } a.zbuffer = (byte *)buffer; a.zbuffer_end = (byte *)buffer + len; if (stbi__do_zlib(&a, p, 16384, 1, 0) != 0) { if (outlen != null) { *outlen = (int)(a.zout - a.zout_start); } return(a.zout_start); } CRuntime.free(a.zout_start); return(null); }
public static sbyte *stbi_zlib_decode_malloc_guesssize_headerflag(sbyte *buffer, int len, int initial_size, int *outlen, int parse_header) { var a = new stbi__zbuf(); var p = (sbyte *)stbi__malloc((ulong)initial_size); if (p == null) { return(null); } a.zbuffer = (byte *)buffer; a.zbuffer_end = (byte *)buffer + len; if (stbi__do_zlib(&a, p, initial_size, 1, parse_header) != 0) { if (outlen != null) { *outlen = (int)(a.zout - a.zout_start); } return(a.zout_start); } CRuntime.free(a.zout_start); return(null); }
static uint stbi__zreceive(stbi__zbuf* z, int n) { uint k; if (z->num_bits < n) stbi__fill_bits(z); k = z->code_buffer & (uint)((1 << n) - 1); z->code_buffer >>= n; z->num_bits -= n; return k; }
//todo continue check static int stbi__zhuffman_decode_slowpath(stbi__zbuf* a, stbi__zhuffman* z) { int b, s, k; // not resolved by fast table, so compute it the slow way // use jpeg approach, which requires MSbits at top k = stbi__bit_reverse((int)a->code_buffer, 16); for (s = STBI__ZFAST_BITS + 1; ; ++s) if (k < z->maxcode[s]) break; if (s == 16) return -1; // invalid code! // code size is s, so: b = (k >> (16 - s)) - z->firstcode[s] + z->firstsymbol[s]; Debug.Assert(z->size[b] == s); a->code_buffer >>= s; a->num_bits -= s; return z->value[b]; }
static int stbi__zhuffman_decode(stbi__zbuf* a, stbi__zhuffman* z) { int b, s; if (a->num_bits < 16) stbi__fill_bits(a); b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b != 0) { s = b >> 9; a->code_buffer >>= s; a->num_bits -= s; return b & 511; } return stbi__zhuffman_decode_slowpath(a, z); }
static byte stbi__zget8(stbi__zbuf* z) { if (z->zbuffer >= z->zbuffer_end) return 0; return *z->zbuffer++; }
// need to make room for n bytes static int stbi__zexpand(stbi__zbuf* z, sbyte* zout, int n) { sbyte* q; int cur, limit; z->zout = zout; if (z->z_expandable == 0) throw new Exception("output buffer limit:Corrupt PNG"); cur = (int)(z->zout - z->zout_start); limit = (int)(z->zout_end - z->zout_start); while (cur + n > limit) limit *= 2; q = (sbyte*)CLib.CStdlib.realloc(z->zout_start, limit); if (q == null) throw new Exception("outofmem:Out of memory"); z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit; return 1; }
static int stbi__parse_zlib_header(stbi__zbuf* a) { int cmf = stbi__zget8(a); int cm = cmf & 15; /* int cinfo = cmf >> 4; */ int flg = stbi__zget8(a); if ((cmf * 256 + flg) % 31 != 0) throw new Exception("bad zlib header:Corrupt PNG"); // zlib spec if ((flg & 32) != 0) throw new Exception("no preset dict:Corrupt PNG"); // preset dictionary not allowed in png if (cm != 8) throw new Exception("bad compression:Corrupt PNG"); // DEFLATE required for png // window = 1 << (8 + cinfo)... but who cares, we fully buffer output return 1; }
static int stbi__parse_zlib(stbi__zbuf* a, int parse_header) { int final, type; if (parse_header != 0) if (stbi__parse_zlib_header(a) == 0) return 0; a->num_bits = 0; a->code_buffer = 0; do { final = (int)stbi__zreceive(a, 1); type = (int)stbi__zreceive(a, 2); if (type == 0) { if (stbi__parse_uncomperssed_block(a) == 0) return 0; } else if (type == 3) { return 0; } else { if (type == 1) { // use fixed code lengths if (stbi__zdefault_distance[31] == 0) stbi__init_zdefaults(); if (stbi__zbuild_huffman(&a->z_length, stbi__zdefault_length, 288) == 0) return 0; if (stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32) == 0) return 0; } else { if (stbi__compute_huffman_codes(a) == 0) return 0; } if (stbi__parse_huffman_block(a) == 0) return 0; } } while (final == 0); return 1; }
static int stbi__parse_uncomperssed_block(stbi__zbuf* a) { byte* header = stackalloc byte[4]; int len, nlen, k; if ((a->num_bits & 7) != 0) stbi__zreceive(a, a->num_bits & 7); // discard // drain the bit-packed data into header k = 0; while (a->num_bits > 0) { header[k++] = (byte)(a->code_buffer & 255); // suppress MSVC run-time check a->code_buffer >>= 8; a->num_bits -= 8; } Debug.Assert(a->num_bits == 0); // now fill header the normal way while (k < 4) header[k++] = stbi__zget8(a); len = header[1] * 256 + header[0]; nlen = header[3] * 256 + header[2]; if (nlen != (len ^ 0xffff)) throw new Exception("zlib corrupt:Corrupt PNG"); if (a->zbuffer + len > a->zbuffer_end) throw new Exception("read past buffer:Corrupt PNG"); if (a->zout + len > a->zout_end) if (stbi__zexpand(a, a->zout, len) == 0) return 0; CLib.CString.memcpy(a->zout, a->zbuffer, (uint)len); a->zbuffer += len; a->zout += len; return 1; }
static int stbi__parse_huffman_block(stbi__zbuf* a) { sbyte* zout = a->zout; for (; ; ) { int z = stbi__zhuffman_decode(a, &a->z_length); if (z < 256) { if (z < 0) throw new Exception("bad huffman code:Corrupt PNG"); // error in huffman codes if (zout >= a->zout_end) { if (stbi__zexpand(a, zout, 1) == 0) return 0; zout = a->zout; } *zout++ = (sbyte)z; } else { byte* p; int len, dist; if (z == 256) { a->zout = zout; return 1; } z -= 257; len = stbi__zlength_base[z]; if (stbi__zlength_extra[z] != 0) len += (int)stbi__zreceive(a, stbi__zlength_extra[z]); z = stbi__zhuffman_decode(a, &a->z_distance); if (z < 0) throw new Exception("bad huffman code:Corrupt PNG"); dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z] != 0) dist += (int)stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) throw new Exception("bad dist:Corrupt PNG"); if (zout + len > a->zout_end) { if (stbi__zexpand(a, zout, len) == 0) return 0; zout = a->zout; } p = (byte*)(zout - dist); if (dist == 1) { // run of one byte; common in images. byte v = *p; if (len != 0) { do *zout++ = (sbyte)v; while ((--len) != 0); } } else { if (len != 0) { do *zout++ = (sbyte)*p++; while ((--len) != 0); } } } } }
static void stbi__fill_bits(stbi__zbuf* z) { do { Debug.Assert(z->code_buffer < (1U << z->num_bits)); z->code_buffer |= (uint)(stbi__zget8(z) << z->num_bits); z->num_bits += 8; } while (z->num_bits <= 24); }
static int stbi__do_zlib(stbi__zbuf* a, sbyte* obuf, int olen, int exp, int parse_header) { a->zout_start = obuf; a->zout = obuf; a->zout_end = obuf + olen; a->z_expandable = exp; return stbi__parse_zlib(a, parse_header); }
static int stbi__compute_huffman_codes(stbi__zbuf* a) { byte* length_dezigzag = stackalloc byte[19]; length_dezigzag[0] = 16; length_dezigzag[1] = 17; length_dezigzag[2] = 18; length_dezigzag[3] = 0; length_dezigzag[4] = 8; length_dezigzag[5] = 7; length_dezigzag[6] = 9; length_dezigzag[7] = 6; length_dezigzag[8] = 10; length_dezigzag[9] = 5; length_dezigzag[10] = 11; length_dezigzag[11] = 4; length_dezigzag[12] = 12; length_dezigzag[13] = 3; length_dezigzag[14] = 13; length_dezigzag[15] = 2; length_dezigzag[16] = 14; length_dezigzag[17] = 1; length_dezigzag[18] = 15; stbi__zhuffman z_codelength; byte* lencodes = stackalloc byte[286 + 32 + 137];//padding for maximum single op byte* codelength_sizes = stackalloc byte[19]; int i, n; int hlit = (int)stbi__zreceive(a, 5) + 257; int hdist = (int)stbi__zreceive(a, 5) + 1; int hclen = (int)stbi__zreceive(a, 4) + 4; CLib.CString.memset(codelength_sizes, 0, 19); for (i = 0; i < hclen; ++i) { int s = (int)stbi__zreceive(a, 3); codelength_sizes[length_dezigzag[i]] = (byte)s; } if (stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19) == 0) return 0; n = 0; while (n < hlit + hdist) { int c = stbi__zhuffman_decode(a, &z_codelength); if (c < 0 || c >= 19) throw new Exception("bad codelengths:Corrupt PNG"); if (c < 16) lencodes[n++] = (byte)c; else if (c == 16) { c = (int)stbi__zreceive(a, 2) + 3; CLib.CString.memset(lencodes + n, lencodes[n - 1], c); n += c; } else if (c == 17) { c = (int)stbi__zreceive(a, 3) + 3; CLib.CString.memset(lencodes + n, 0, c); n += c; } else { Debug.Assert(c == 18); c = (int)stbi__zreceive(a, 7) + 11; CLib.CString.memset(lencodes + n, 0, c); n += c; } } if (n != hlit + hdist) throw new Exception("bad codelengths:Corrupt PNG"); if (stbi__zbuild_huffman(&a->z_length, lencodes, hlit) == 0) return 0; if (stbi__zbuild_huffman(&a->z_distance, lencodes + hlit, hdist) == 0) return 0; return 1; }