public static int stbi__create_png_image(stbi__png a, byte *image_data, uint image_data_len, int out_n, int depth, int color, int interlaced) { var bytes = depth == 16 ? 2 : 1; var out_bytes = out_n * bytes; byte *final; var p = 0; if (interlaced == 0) { return(stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a.s.img_x, a.s.img_y, depth, color)); } final = (byte *)stbi__malloc_mad3((int)a.s.img_x, (int)a.s.img_y, out_bytes, 0); if (final == null) { return(stbi__err("outofmem")); } for (p = 0; p < 7; ++p) { var xorig = stackalloc int[] { 0, 4, 0, 2, 0, 1, 0 }; var yorig = stackalloc int[] { 0, 0, 4, 0, 2, 0, 1 }; var xspc = stackalloc int[] { 8, 8, 4, 4, 2, 2, 1 }; var yspc = stackalloc int[] { 8, 8, 8, 4, 4, 2, 2 }; var i = 0; var j = 0; var x = 0; var y = 0; x = (int)((a.s.img_x - xorig[p] + xspc[p] - 1) / xspc[p]); y = (int)((a.s.img_y - yorig[p] + yspc[p] - 1) / yspc[p]); if (x != 0 && y != 0) { var img_len = (uint)((((a.s.img_n * x * depth + 7) >> 3) + 1) * y); if (stbi__create_png_image_raw(a, image_data, image_data_len, out_n, (uint)x, (uint)y, depth, color) == 0) { CRuntime.free(final); return(0); } for (j = 0; j < y; ++j) { for (i = 0; i < x; ++i) { var out_y = j * yspc[p] + yorig[p]; var out_x = i * xspc[p] + xorig[p]; CRuntime.memcpy(final + out_y * a.s.img_x * out_bytes + out_x * out_bytes, a._out_ + (j * x + i) * out_bytes, (ulong)out_bytes); } } CRuntime.free(a._out_); image_data += img_len; image_data_len -= img_len; } } a._out_ = final; return(1); }
public static int stbi__parse_uncompressed_block(stbi__zbuf *a) { var header = stackalloc byte[4]; var len = 0; var nlen = 0; var k = 0; if ((a->num_bits & 7) != 0) { stbi__zreceive(a, a->num_bits & 7); } k = 0; while (a->num_bits > 0) { header[k++] = (byte)(a->code_buffer & 255); a->code_buffer >>= 8; a->num_bits -= 8; } if (a->num_bits < 0) { return(stbi__err("zlib corrupt")); } while (k < 4) { header[k++] = stbi__zget8(a); } len = header[1] * 256 + header[0]; nlen = header[3] * 256 + header[2]; if (nlen != (len ^ 0xffff)) { return(stbi__err("zlib corrupt")); } if (a->zbuffer + len > a->zbuffer_end) { return(stbi__err("read past buffer")); } if (a->zout + len > a->zout_end) { if (stbi__zexpand(a, a->zout, len) == 0) { return(0); } } CRuntime.memcpy(a->zout, a->zbuffer, (ulong)len); a->zbuffer += len; a->zout += len; return(1); }
public static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) { var row = 0; var bytes_per_row = (ulong)(w * bytes_per_pixel); var temp = stackalloc byte[2048]; var bytes = (byte *)image; for (row = 0; row < h >> 1; row++) { var row0 = bytes + (ulong)row * bytes_per_row; var row1 = bytes + (ulong)(h - row - 1) * bytes_per_row; var bytes_left = bytes_per_row; while (bytes_left != 0) { var bytes_copy = bytes_left < 2048 ? bytes_left : 2048; CRuntime.memcpy(temp, row0, bytes_copy); CRuntime.memcpy(row0, row1, bytes_copy); CRuntime.memcpy(row1, temp, bytes_copy); row0 += bytes_copy; row1 += bytes_copy; bytes_left -= bytes_copy; } } }
public static void *stbi__load_gif_main(stbi__context s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { if (stbi__gif_test(s) != 0) { var layers = 0; byte *u = null; byte *_out_ = null; byte *two_back = null; var g = new stbi__gif(); var stride = 0; var out_size = 0; var delays_size = 0; if (delays != null) { *delays = null; } do { u = stbi__gif_load_next(s, g, comp, req_comp, two_back); if (u != null) { *x = g.w; *y = g.h; ++layers; stride = g.w * g.h * 4; if (_out_ != null) { void *tmp = (byte *)CRuntime.realloc(_out_, (ulong)(layers * stride)); if (tmp == null) { return(stbi__load_gif_main_outofmem(g, _out_, delays)); } _out_ = (byte *)tmp; out_size = layers * stride; if (delays != null) { var new_delays = (int *)CRuntime.realloc(*delays, (ulong)(sizeof(int) * layers)); if (new_delays == null) { return(stbi__load_gif_main_outofmem(g, _out_, delays)); } *delays = new_delays; delays_size = layers * sizeof(int); } } else { _out_ = (byte *)stbi__malloc((ulong)(layers * stride)); if (_out_ == null) { return(stbi__load_gif_main_outofmem(g, _out_, delays)); } out_size = layers * stride; if (delays != null) { *delays = (int *)stbi__malloc((ulong)(layers * sizeof(int))); if (*delays == null) { return(stbi__load_gif_main_outofmem(g, _out_, delays)); } delays_size = layers * sizeof(int); } } CRuntime.memcpy(_out_ + (layers - 1) * stride, u, (ulong)stride); if (layers >= 2) { two_back = _out_ - 2 * stride; } if (delays != null) { (*delays)[layers - 1U] = g.delay; } } } while (u != null); CRuntime.free(g._out_); CRuntime.free(g.history); CRuntime.free(g.background); if (req_comp != 0 && req_comp != 4) { _out_ = stbi__convert_format(_out_, 4, req_comp, (uint)(layers * g.w), (uint)g.h); } *z = layers; return(_out_); } return((byte *)(ulong)(stbi__err("not GIF") != 0 ? 0 : 0)); }
public static byte *stbi__gif_load_next(stbi__context s, stbi__gif g, int *comp, int req_comp, byte *two_back) { var dispose = 0; var first_frame = 0; var pi = 0; var pcount = 0; first_frame = 0; if (g._out_ == null) { if (stbi__gif_header(s, g, comp, 0) == 0) { return(null); } if (stbi__mad3sizes_valid(4, g.w, g.h, 0) == 0) { return((byte *)(ulong)(stbi__err("too large") != 0 ? 0 : 0)); } pcount = g.w * g.h; g._out_ = (byte *)stbi__malloc((ulong)(4 * pcount)); g.background = (byte *)stbi__malloc((ulong)(4 * pcount)); g.history = (byte *)stbi__malloc((ulong)pcount); if (g._out_ == null || g.background == null || g.history == null) { return((byte *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0)); } CRuntime.memset(g._out_, 0x00, (ulong)(4 * pcount)); CRuntime.memset(g.background, 0x00, (ulong)(4 * pcount)); CRuntime.memset(g.history, 0x00, (ulong)pcount); first_frame = 1; } else { dispose = (g.eflags & 0x1C) >> 2; pcount = g.w * g.h; if (dispose == 3 && two_back == null) { dispose = 2; } if (dispose == 3) { for (pi = 0; pi < pcount; ++pi) { if (g.history[pi] != 0) { CRuntime.memcpy(&g._out_[pi * 4], &two_back[pi * 4], (ulong)4); } } } else if (dispose == 2) { for (pi = 0; pi < pcount; ++pi) { if (g.history[pi] != 0) { CRuntime.memcpy(&g._out_[pi * 4], &g.background[pi * 4], (ulong)4); } } } CRuntime.memcpy(g.background, g._out_, (ulong)(4 * g.w * g.h)); } CRuntime.memset(g.history, 0x00, (ulong)(g.w * g.h)); for (; ;) { int tag = stbi__get8(s); switch (tag) { case 0x2C: { var x = 0; var y = 0; var w = 0; var h = 0; byte *o; x = stbi__get16le(s); y = stbi__get16le(s); w = stbi__get16le(s); h = stbi__get16le(s); if (x + w > g.w || y + h > g.h) { return((byte *)(ulong)(stbi__err("bad Image Descriptor") != 0 ? 0 : 0)); } g.line_size = g.w * 4; g.start_x = x * 4; g.start_y = y * g.line_size; g.max_x = g.start_x + w * 4; g.max_y = g.start_y + h * g.line_size; g.cur_x = g.start_x; g.cur_y = g.start_y; if (w == 0) { g.cur_y = g.max_y; } g.lflags = stbi__get8(s); if ((g.lflags & 0x40) != 0) { g.step = 8 * g.line_size; g.parse = 3; } else { g.step = g.line_size; g.parse = 0; } if ((g.lflags & 0x80) != 0) { stbi__gif_parse_colortable(s, g.lpal, 2 << (g.lflags & 7), (g.eflags & 0x01) != 0 ? g.transparent : -1); g.color_table = (byte *)g.lpal; } else if ((g.flags & 0x80) != 0) { g.color_table = (byte *)g.pal; } else { return((byte *)(ulong)(stbi__err("missing color table") != 0 ? 0 : 0)); } o = stbi__process_gif_raster(s, g); if (o == null) { return(null); } pcount = g.w * g.h; if (first_frame != 0 && g.bgindex > 0) { for (pi = 0; pi < pcount; ++pi) { if (g.history[pi] == 0) { g.pal[g.bgindex][3] = 255; CRuntime.memcpy(&g._out_[pi * 4], &g.pal[g.bgindex], (ulong)4); } } } return(o); } case 0x21: { var len = 0; int ext = stbi__get8(s); if (ext == 0xF9) { len = stbi__get8(s); if (len == 4) { g.eflags = stbi__get8(s); g.delay = 10 * stbi__get16le(s); if (g.transparent >= 0) { g.pal[g.transparent][3] = 255; } if ((g.eflags & 0x01) != 0) { g.transparent = stbi__get8(s); if (g.transparent >= 0) { g.pal[g.transparent][3] = 0; } } else { stbi__skip(s, 1); g.transparent = -1; } } else { stbi__skip(s, len); break; } } while ((len = stbi__get8(s)) != 0) { stbi__skip(s, len); } break; } case 0x3B: return(null); default: return((byte *)(ulong)(stbi__err("unknown code") != 0 ? 0 : 0)); } } }
public static int stbi__create_png_image_raw(stbi__png a, byte *raw, uint raw_len, int out_n, uint x, uint y, int depth, int color) { var bytes = depth == 16 ? 2 : 1; var s = a.s; uint i = 0; uint j = 0; var stride = (uint)(x * out_n * bytes); uint img_len = 0; uint img_width_bytes = 0; var k = 0; var img_n = s.img_n; var output_bytes = out_n * bytes; var filter_bytes = img_n * bytes; var width = (int)x; a._out_ = (byte *)stbi__malloc_mad3((int)x, (int)y, output_bytes, 0); if (a._out_ == null) { return(stbi__err("outofmem")); } if (stbi__mad3sizes_valid(img_n, (int)x, depth, 7) == 0) { return(stbi__err("too large")); } img_width_bytes = (uint)((img_n * x * depth + 7) >> 3); img_len = (img_width_bytes + 1) * y; if (raw_len < img_len) { return(stbi__err("not enough pixels")); } for (j = (uint)0; j < y; ++j) { var cur = a._out_ + stride * j; byte *prior; var filter = (int)*raw++; if (filter > 4) { return(stbi__err("invalid filter")); } if (depth < 8) { cur += x * out_n - img_width_bytes; filter_bytes = 1; width = (int)img_width_bytes; } prior = cur - stride; if (j == 0) { filter = first_row_filter[filter]; } for (k = 0; k < filter_bytes; ++k) { switch (filter) { case STBI__F_none: cur[k] = raw[k]; break; case STBI__F_sub: cur[k] = raw[k]; break; case STBI__F_up: cur[k] = (byte)((raw[k] + prior[k]) & 255); break; case STBI__F_avg: cur[k] = (byte)((raw[k] + (prior[k] >> 1)) & 255); break; case STBI__F_paeth: cur[k] = (byte)((raw[k] + stbi__paeth(0, prior[k], 0)) & 255); break; case STBI__F_avg_first: cur[k] = raw[k]; break; case STBI__F_paeth_first: cur[k] = raw[k]; break; } } if (depth == 8) { if (img_n != out_n) { cur[img_n] = 255; } raw += img_n; cur += out_n; prior += out_n; } else if (depth == 16) { if (img_n != out_n) { cur[filter_bytes] = 255; cur[filter_bytes + 1] = 255; } raw += filter_bytes; cur += output_bytes; prior += output_bytes; } else { raw += 1; cur += 1; prior += 1; } if (depth < 8 || img_n == out_n) { var nk = (width - 1) * filter_bytes; switch (filter) { case STBI__F_none: CRuntime.memcpy(cur, raw, (ulong)nk); break; case STBI__F_sub: for (k = 0; k < nk; ++k) { cur[k] = (byte)((raw[k] + cur[k - filter_bytes]) & 255); } break; case STBI__F_up: for (k = 0; k < nk; ++k) { cur[k] = (byte)((raw[k] + prior[k]) & 255); } break; case STBI__F_avg: for (k = 0; k < nk; ++k) { cur[k] = (byte)((raw[k] + ((prior[k] + cur[k - filter_bytes]) >> 1)) & 255); } break; case STBI__F_paeth: for (k = 0; k < nk; ++k) { cur[k] = (byte)((raw[k] + stbi__paeth(cur[k - filter_bytes], prior[k], prior[k - filter_bytes])) & 255); } break; case STBI__F_avg_first: for (k = 0; k < nk; ++k) { cur[k] = (byte)((raw[k] + (cur[k - filter_bytes] >> 1)) & 255); } break; case STBI__F_paeth_first: for (k = 0; k < nk; ++k) { cur[k] = (byte)((raw[k] + stbi__paeth(cur[k - filter_bytes], 0, 0)) & 255); } break; } raw += nk; } else { switch (filter) { case STBI__F_none: for (i = x - 1; i >= 1; --i, cur[filter_bytes] = (byte)255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) { for (k = 0; k < filter_bytes; ++k) { cur[k] = raw[k]; } } break; case STBI__F_sub: for (i = x - 1; i >= 1; --i, cur[filter_bytes] = (byte)255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) { for (k = 0; k < filter_bytes; ++k) { cur[k] = (byte)((raw[k] + cur[k - output_bytes]) & 255); } } break; case STBI__F_up: for (i = x - 1; i >= 1; --i, cur[filter_bytes] = (byte)255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) { for (k = 0; k < filter_bytes; ++k) { cur[k] = (byte)((raw[k] + prior[k]) & 255); } } break; case STBI__F_avg: for (i = x - 1; i >= 1; --i, cur[filter_bytes] = (byte)255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) { for (k = 0; k < filter_bytes; ++k) { cur[k] = (byte)((raw[k] + ((prior[k] + cur[k - output_bytes]) >> 1)) & 255); } } break; case STBI__F_paeth: for (i = x - 1; i >= 1; --i, cur[filter_bytes] = (byte)255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) { for (k = 0; k < filter_bytes; ++k) { cur[k] = (byte)((raw[k] + stbi__paeth(cur[k - output_bytes], prior[k], prior[k - output_bytes])) & 255); } } break; case STBI__F_avg_first: for (i = x - 1; i >= 1; --i, cur[filter_bytes] = (byte)255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) { for (k = 0; k < filter_bytes; ++k) { cur[k] = (byte)((raw[k] + (cur[k - output_bytes] >> 1)) & 255); } } break; case STBI__F_paeth_first: for (i = x - 1; i >= 1; --i, cur[filter_bytes] = (byte)255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) { for (k = 0; k < filter_bytes; ++k) { cur[k] = (byte)((raw[k] + stbi__paeth(cur[k - output_bytes], 0, 0)) & 255); } } break; } if (depth == 16) { cur = a._out_ + stride * j; for (i = (uint)0; i < x; ++i, cur += output_bytes) { cur[filter_bytes + 1] = 255; } } } } if (depth < 8) { for (j = (uint)0; j < y; ++j) { var cur = a._out_ + stride * j; var _in_ = a._out_ + stride * j + x * out_n - img_width_bytes; var scale = (byte)(color == 0 ? stbi__depth_scale_table[depth] : 1); if (depth == 4) { for (k = (int)(x * img_n); k >= 2; k -= 2, ++_in_) { *cur++ = (byte)(scale * (*_in_ >> 4)); *cur++ = (byte)(scale * (*_in_ & 0x0f)); } if (k > 0) { *cur++ = (byte)(scale * (*_in_ >> 4)); } } else if (depth == 2) { for (k = (int)(x * img_n); k >= 4; k -= 4, ++_in_) { *cur++ = (byte)(scale * (*_in_ >> 6)); *cur++ = (byte)(scale * ((*_in_ >> 4) & 0x03)); *cur++ = (byte)(scale * ((*_in_ >> 2) & 0x03)); *cur++ = (byte)(scale * (*_in_ & 0x03)); } if (k > 0) { *cur++ = (byte)(scale * (*_in_ >> 6)); } if (k > 1) { *cur++ = (byte)(scale * ((*_in_ >> 4) & 0x03)); } if (k > 2) { *cur++ = (byte)(scale * ((*_in_ >> 2) & 0x03)); } } else if (depth == 1) { for (k = (int)(x * img_n); k >= 8; k -= 8, ++_in_) { *cur++ = (byte)(scale * (*_in_ >> 7)); *cur++ = (byte)(scale * ((*_in_ >> 6) & 0x01)); *cur++ = (byte)(scale * ((*_in_ >> 5) & 0x01)); *cur++ = (byte)(scale * ((*_in_ >> 4) & 0x01)); *cur++ = (byte)(scale * ((*_in_ >> 3) & 0x01)); *cur++ = (byte)(scale * ((*_in_ >> 2) & 0x01)); *cur++ = (byte)(scale * ((*_in_ >> 1) & 0x01)); *cur++ = (byte)(scale * (*_in_ & 0x01)); } if (k > 0) { *cur++ = (byte)(scale * (*_in_ >> 7)); } if (k > 1) { *cur++ = (byte)(scale * ((*_in_ >> 6) & 0x01)); } if (k > 2) { *cur++ = (byte)(scale * ((*_in_ >> 5) & 0x01)); } if (k > 3) { *cur++ = (byte)(scale * ((*_in_ >> 4) & 0x01)); } if (k > 4) { *cur++ = (byte)(scale * ((*_in_ >> 3) & 0x01)); } if (k > 5) { *cur++ = (byte)(scale * ((*_in_ >> 2) & 0x01)); } if (k > 6) { *cur++ = (byte)(scale * ((*_in_ >> 1) & 0x01)); } } if (img_n != out_n) { var q = 0; cur = a._out_ + stride * j; if (img_n == 1) { for (q = (int)(x - 1); q >= 0; --q) { cur[q * 2 + 1] = 255; cur[q * 2 + 0] = cur[q]; } } else { for (q = (int)(x - 1); q >= 0; --q) { cur[q * 4 + 3] = 255; cur[q * 4 + 2] = cur[q * 3 + 2]; cur[q * 4 + 1] = cur[q * 3 + 1]; cur[q * 4 + 0] = cur[q * 3 + 0]; } } } } } else if (depth == 16) { var cur = a._out_; var cur16 = (ushort *)cur; for (i = (uint)0; i < x * y * out_n; ++i, cur16++, cur += 2) { *cur16 = (ushort)((cur[0] << 8) | cur[1]); } } return(1); }