Beispiel #1
0
        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
            });
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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();
                    }
                }
            }
        }
Beispiel #4
0
        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_
            });
        }
Beispiel #5
0
        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_);
        }