public static ImageInfo?Info(Stream stream) { var info = new stbi__bmp_data { all_a = 255 }; var decoder = new BmpDecoder(stream); try { decoder.stbi__bmp_parse_header(ref info); } catch (Exception) { return(null); } finally { stream.Rewind(); } return(new ImageInfo { Width = decoder.img_x, Height = decoder.img_y, ColorComponents = info.ma != 0 ? ColorComponents.RedGreenBlueAlpha : ColorComponents.RedGreenBlue, BitsPerChannel = 8 }); }
public static int stbi__bmp_info(stbi__context s, int *x, int *y, int *comp) { void *p; var info = new stbi__bmp_data(); info.all_a = 255; p = stbi__bmp_parse_header(s, &info); stbi__rewind(s); if (p == null) { return(0); } if (x != null) { *x = (int)s.img_x; } if (y != null) { *y = (int)s.img_y; } if (comp != null) { *comp = info.ma != 0 ? 4 : 3; } return(1); }
private void stbi__bmp_parse_header(ref stbi__bmp_data info) { var hsz = 0; if (stbi__get8() != 'B' || stbi__get8() != 'M') { stbi__err("not BMP"); } stbi__get32le(); stbi__get16le(); stbi__get16le(); info.offset = (int)stbi__get32le(); info.hsz = hsz = (int)stbi__get32le(); info.mr = info.mg = info.mb = info.ma = 0; if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) { stbi__err("unknown BMP"); } if (hsz == 12) { img_x = stbi__get16le(); img_y = stbi__get16le(); } else { img_x = (int)stbi__get32le(); img_y = (int)stbi__get32le(); } if (stbi__get16le() != 1) { stbi__err("bad BMP"); } info.bpp = stbi__get16le(); if (hsz != 12) { var compress = (int)stbi__get32le(); if (compress == 1 || compress == 2) { stbi__err("BMP RLE"); } stbi__get32le(); stbi__get32le(); stbi__get32le(); stbi__get32le(); stbi__get32le(); if (hsz == 40 || hsz == 56) { if (hsz == 56) { stbi__get32le(); stbi__get32le(); stbi__get32le(); stbi__get32le(); } if (info.bpp == 16 || info.bpp == 32) { if (compress == 0) { if (info.bpp == 32) { info.mr = 0xffu << 16; info.mg = 0xffu << 8; info.mb = 0xffu << 0; info.ma = 0xffu << 24; info.all_a = 0; } else { info.mr = 31u << 10; info.mg = 31u << 5; info.mb = 31u << 0; } } else if (compress == 3) { info.mr = stbi__get32le(); info.mg = stbi__get32le(); info.mb = stbi__get32le(); if (info.mr == info.mg && info.mg == info.mb) { stbi__err("bad BMP"); } } else { stbi__err("bad BMP"); } } } else { var i = 0; if (hsz != 108 && hsz != 124) { stbi__err("bad BMP"); } info.mr = stbi__get32le(); info.mg = stbi__get32le(); info.mb = stbi__get32le(); info.ma = stbi__get32le(); stbi__get32le(); for (i = 0; i < 12; ++i) { stbi__get32le(); } if (hsz == 124) { stbi__get32le(); stbi__get32le(); stbi__get32le(); stbi__get32le(); } } } }
private ImageResult InternalDecode(ColorComponents?requiredComponents) { byte[] _out_; var mr = (uint)0; var mg = (uint)0; var mb = (uint)0; var ma = (uint)0; uint all_a = 0; var pal = new byte[256 * 4]; var psize = 0; var i = 0; var j = 0; var width = 0; var flip_vertically = 0; var pad = 0; var target = 0; var info = new stbi__bmp_data(); info.all_a = 255; stbi__bmp_parse_header(ref info); flip_vertically = img_y > 0 ? 1 : 0; img_y = Math.Abs(img_y); mr = info.mr; mg = info.mg; mb = info.mb; ma = info.ma; all_a = info.all_a; if (info.hsz == 12) { if (info.bpp < 24) { psize = (info.offset - 14 - 24) / 3; } } else { if (info.bpp < 16) { psize = (info.offset - 14 - info.hsz) >> 2; } } img_n = ma != 0 ? 4 : 3; if (requiredComponents != null && (int)requiredComponents.Value >= 3) { target = (int)requiredComponents.Value; } else { target = img_n; } _out_ = new byte[target * img_x * img_y]; if (info.bpp < 16) { var z = 0; if (psize == 0 || psize > 256) { stbi__err("invalid"); } for (i = 0; i < psize; ++i) { pal[i * 4 + 2] = stbi__get8(); pal[i * 4 + 1] = stbi__get8(); pal[i * 4 + 0] = stbi__get8(); if (info.hsz != 12) { stbi__get8(); } pal[i * 4 + 3] = 255; } stbi__skip(info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); if (info.bpp == 1) { width = (img_x + 7) >> 3; } else if (info.bpp == 4) { width = (img_x + 1) >> 1; } else if (info.bpp == 8) { width = img_x; } else { stbi__err("bad bpp"); } pad = -width & 3; if (info.bpp == 1) { for (j = 0; j < img_y; ++j) { var bit_offset = 7; var v = (int)stbi__get8(); for (i = 0; i < img_x; ++i) { var color = (v >> bit_offset) & 0x1; _out_[z++] = pal[color * 4 + 0]; _out_[z++] = pal[color * 4 + 1]; _out_[z++] = pal[color * 4 + 2]; if (target == 4) { _out_[z++] = 255; } if (i + 1 == img_x) { break; } if (--bit_offset < 0) { bit_offset = 7; v = stbi__get8(); } } stbi__skip(pad); } } else { for (j = 0; j < img_y; ++j) { for (i = 0; i < img_x; i += 2) { var v = (int)stbi__get8(); var v2 = 0; if (info.bpp == 4) { v2 = v & 15; v >>= 4; } _out_[z++] = pal[v * 4 + 0]; _out_[z++] = pal[v * 4 + 1]; _out_[z++] = pal[v * 4 + 2]; if (target == 4) { _out_[z++] = 255; } if (i + 1 == img_x) { break; } v = info.bpp == 8 ? stbi__get8() : v2; _out_[z++] = pal[v * 4 + 0]; _out_[z++] = pal[v * 4 + 1]; _out_[z++] = pal[v * 4 + 2]; if (target == 4) { _out_[z++] = 255; } } stbi__skip(pad); } } } else { var rshift = 0; var gshift = 0; var bshift = 0; var ashift = 0; var rcount = 0; var gcount = 0; var bcount = 0; var acount = 0; var z = 0; var easy = 0; stbi__skip(info.offset - 14 - info.hsz); if (info.bpp == 24) { width = 3 * img_x; } else if (info.bpp == 16) { width = 2 * img_x; } else { width = 0; } pad = -width & 3; if (info.bpp == 24) { easy = 1; } else if (info.bpp == 32) { if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) { easy = 2; } } if (easy == 0) { if (mr == 0 || mg == 0 || mb == 0) { stbi__err("bad masks"); } rshift = stbi__high_bit(mr) - 7; rcount = stbi__bitcount(mr); gshift = stbi__high_bit(mg) - 7; gcount = stbi__bitcount(mg); bshift = stbi__high_bit(mb) - 7; bcount = stbi__bitcount(mb); ashift = stbi__high_bit(ma) - 7; acount = stbi__bitcount(ma); } for (j = 0; j < img_y; ++j) { if (easy != 0) { for (i = 0; i < img_x; ++i) { byte a = 0; _out_[z + 2] = stbi__get8(); _out_[z + 1] = stbi__get8(); _out_[z + 0] = stbi__get8(); z += 3; a = (byte)(easy == 2 ? stbi__get8() : 255); all_a |= a; if (target == 4) { _out_[z++] = a; } } } else { var bpp = info.bpp; for (i = 0; i < img_x; ++i) { var v = bpp == 16 ? (uint)stbi__get16le() : stbi__get32le(); uint a = 0; _out_[z++] = (byte)(stbi__shiftsigned(v & mr, rshift, rcount) & 255); _out_[z++] = (byte)(stbi__shiftsigned(v & mg, gshift, gcount) & 255); _out_[z++] = (byte)(stbi__shiftsigned(v & mb, bshift, bcount) & 255); a = (uint)(ma != 0 ? stbi__shiftsigned(v & ma, ashift, acount) : 255); all_a |= a; if (target == 4) { _out_[z++] = (byte)(a & 255); } } } stbi__skip(pad); } } if (target == 4 && all_a == 0) { for (i = 4 * img_x * img_y - 1; i >= 0; i -= 4) { _out_[i] = 255; } } if (flip_vertically != 0) { byte t = 0; var ptr = new FakePtr <byte>(_out_); for (j = 0; j < img_y >> 1; ++j) { var p1 = ptr + j * img_x * target; var p2 = ptr + (img_y - 1 - j) * img_x * target; for (i = 0; i < img_x * target; ++i) { t = p1[i]; p1[i] = p2[i]; p2[i] = t; } } } if (requiredComponents != null && (int)requiredComponents.Value != target) { _out_ = Conversion.stbi__convert_format(_out_, target, (int)requiredComponents.Value, (uint)img_x, (uint)img_y); } return(new ImageResult { Width = img_x, Height = img_y, SourceComponents = (ColorComponents)img_n, ColorComponents = requiredComponents != null ? requiredComponents.Value : (ColorComponents)img_n, BitsPerChannel = 8, Data = _out_ }); }
public static void *stbi__bmp_load(stbi__context s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { byte *_out_; var mr = (uint)0; var mg = (uint)0; var mb = (uint)0; var ma = (uint)0; uint all_a = 0; var pal = stackalloc byte[256 * 4]; var psize = 0; var i = 0; var j = 0; var width = 0; var flip_vertically = 0; var pad = 0; var target = 0; var info = new stbi__bmp_data(); info.all_a = 255; if (stbi__bmp_parse_header(s, &info) == null) { return(null); } flip_vertically = (int)s.img_y > 0 ? 1 : 0; s.img_y = (uint)CRuntime.abs((int)s.img_y); mr = info.mr; mg = info.mg; mb = info.mb; ma = info.ma; all_a = info.all_a; if (info.hsz == 12) { if (info.bpp < 24) { psize = (info.offset - 14 - 24) / 3; } } else { if (info.bpp < 16) { psize = (info.offset - 14 - info.hsz) >> 2; } } s.img_n = ma != 0 ? 4 : 3; if (req_comp != 0 && req_comp >= 3) { target = req_comp; } else { target = s.img_n; } if (stbi__mad3sizes_valid(target, (int)s.img_x, (int)s.img_y, 0) == 0) { return((byte *)(ulong)(stbi__err("too large") != 0 ? (byte *)null : null)); } _out_ = (byte *)stbi__malloc_mad3(target, (int)s.img_x, (int)s.img_y, 0); if (_out_ == null) { return((byte *)(ulong)(stbi__err("outofmem") != 0 ? (byte *)null : null)); } if (info.bpp < 16) { var z = 0; if (psize == 0 || psize > 256) { CRuntime.free(_out_); return((byte *)(ulong)(stbi__err("invalid") != 0 ? (byte *)null : null)); } for (i = 0; i < psize; ++i) { pal[i * 4 + 2] = stbi__get8(s); pal[i * 4 + 1] = stbi__get8(s); pal[i * 4 + 0] = stbi__get8(s); if (info.hsz != 12) { stbi__get8(s); } pal[i * 4 + 3] = 255; } stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); if (info.bpp == 1) { width = (int)((s.img_x + 7) >> 3); } else if (info.bpp == 4) { width = (int)((s.img_x + 1) >> 1); } else if (info.bpp == 8) { width = (int)s.img_x; } else { CRuntime.free(_out_); return((byte *)(ulong)(stbi__err("bad bpp") != 0 ? (byte *)null : null)); } pad = -width & 3; if (info.bpp == 1) { for (j = 0; j < (int)s.img_y; ++j) { var bit_offset = 7; var v = (int)stbi__get8(s); for (i = 0; i < (int)s.img_x; ++i) { var color = (v >> bit_offset) & 0x1; _out_[z++] = pal[color * 4 + 0]; _out_[z++] = pal[color * 4 + 1]; _out_[z++] = pal[color * 4 + 2]; if (target == 4) { _out_[z++] = 255; } if (i + 1 == (int)s.img_x) { break; } if (--bit_offset < 0) { bit_offset = 7; v = stbi__get8(s); } } stbi__skip(s, pad); } } else { for (j = 0; j < (int)s.img_y; ++j) { for (i = 0; i < (int)s.img_x; i += 2) { var v = (int)stbi__get8(s); var v2 = 0; if (info.bpp == 4) { v2 = v & 15; v >>= 4; } _out_[z++] = pal[v * 4 + 0]; _out_[z++] = pal[v * 4 + 1]; _out_[z++] = pal[v * 4 + 2]; if (target == 4) { _out_[z++] = 255; } if (i + 1 == (int)s.img_x) { break; } v = info.bpp == 8 ? stbi__get8(s) : v2; _out_[z++] = pal[v * 4 + 0]; _out_[z++] = pal[v * 4 + 1]; _out_[z++] = pal[v * 4 + 2]; if (target == 4) { _out_[z++] = 255; } } stbi__skip(s, pad); } } } else { var rshift = 0; var gshift = 0; var bshift = 0; var ashift = 0; var rcount = 0; var gcount = 0; var bcount = 0; var acount = 0; var z = 0; var easy = 0; stbi__skip(s, info.offset - 14 - info.hsz); if (info.bpp == 24) { width = (int)(3 * s.img_x); } else if (info.bpp == 16) { width = (int)(2 * s.img_x); } else { width = 0; } pad = -width & 3; if (info.bpp == 24) { easy = 1; } else if (info.bpp == 32) { if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) { easy = 2; } } if (easy == 0) { if (mr == 0 || mg == 0 || mb == 0) { CRuntime.free(_out_); return((byte *)(ulong)(stbi__err("bad masks") != 0 ? (byte *)null : null)); } rshift = stbi__high_bit(mr) - 7; rcount = stbi__bitcount(mr); gshift = stbi__high_bit(mg) - 7; gcount = stbi__bitcount(mg); bshift = stbi__high_bit(mb) - 7; bcount = stbi__bitcount(mb); ashift = stbi__high_bit(ma) - 7; acount = stbi__bitcount(ma); } for (j = 0; j < (int)s.img_y; ++j) { if (easy != 0) { for (i = 0; i < (int)s.img_x; ++i) { byte a = 0; _out_[z + 2] = stbi__get8(s); _out_[z + 1] = stbi__get8(s); _out_[z + 0] = stbi__get8(s); z += 3; a = (byte)(easy == 2 ? stbi__get8(s) : 255); all_a |= a; if (target == 4) { _out_[z++] = a; } } } else { var bpp = info.bpp; for (i = 0; i < (int)s.img_x; ++i) { var v = bpp == 16 ? (uint)stbi__get16le(s) : stbi__get32le(s); uint a = 0; _out_[z++] = (byte)(stbi__shiftsigned(v & mr, rshift, rcount) & 255); _out_[z++] = (byte)(stbi__shiftsigned(v & mg, gshift, gcount) & 255); _out_[z++] = (byte)(stbi__shiftsigned(v & mb, bshift, bcount) & 255); a = (uint)(ma != 0 ? stbi__shiftsigned(v & ma, ashift, acount) : 255); all_a |= a; if (target == 4) { _out_[z++] = (byte)(a & 255); } } } stbi__skip(s, pad); } } if (target == 4 && all_a == 0) { for (i = (int)(4 * s.img_x * s.img_y - 1); i >= 0; i -= 4) { _out_[i] = 255; } } if (flip_vertically != 0) { byte t = 0; for (j = 0; j < (int)s.img_y >> 1; ++j) { var p1 = _out_ + j * s.img_x * target; var p2 = _out_ + (s.img_y - 1 - j) * s.img_x * target; for (i = 0; i < (int)s.img_x * target; ++i) { t = p1[i]; p1[i] = p2[i]; p2[i] = t; } } } if (req_comp != 0 && req_comp != target) { _out_ = stbi__convert_format(_out_, target, req_comp, s.img_x, s.img_y); if (_out_ == null) { return(_out_); } } *x = (int)s.img_x; *y = (int)s.img_y; if (comp != null) { *comp = s.img_n; } return(_out_); }