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; } 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 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); }
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); for (p = 0; p < 7; ++p) { var xorig = stackalloc int[7]; xorig[0] = 0; xorig[1] = 4; xorig[2] = 0; xorig[3] = 2; xorig[4] = 0; xorig[5] = 1; xorig[6] = 0; var yorig = stackalloc int[7]; yorig[0] = 0; yorig[1] = 0; yorig[2] = 4; yorig[3] = 0; yorig[4] = 2; yorig[5] = 0; yorig[6] = 1; var xspc = stackalloc int[7]; xspc[0] = 8; xspc[1] = 8; xspc[2] = 4; xspc[3] = 4; xspc[4] = 2; xspc[5] = 2; xspc[6] = 1; var yspc = stackalloc int[7]; yspc[0] = 8; yspc[1] = 8; yspc[2] = 8; yspc[3] = 4; yspc[4] = 4; yspc[5] = 2; yspc[6] = 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); }