Пример #1
0
        public static int stbi__zexpand(stbi__zbuf *z, sbyte *zout, int n)
        {
            sbyte *q;
            var    cur       = 0;
            var    limit     = 0;
            var    old_limit = 0;

            z->zout = zout;
            if (z->z_expandable == 0)
            {
                return(stbi__err("output buffer limit"));
            }
            cur   = (int)(z->zout - z->zout_start);
            limit = old_limit = (int)(z->zout_end - z->zout_start);
            while (cur + n > limit)
            {
                limit *= 2;
            }
            q = (sbyte *)CRuntime.realloc(z->zout_start, (ulong)limit);
            if (q == null)
            {
                return(stbi__err("outofmem"));
            }
            z->zout_start = q;
            z->zout       = q + cur;
            z->zout_end   = q + limit;
            return(1);
        }
Пример #2
0
        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 int stbi__parse_png_file(stbi__png z, int scan, int req_comp)
        {
            var palette   = stackalloc byte[1024];
            var pal_img_n = (byte)0;
            var has_trans = (byte)0;
            var tc        = stackalloc byte[3];

            tc[0] = 0;

            var  tc16        = stackalloc ushort[3];
            var  ioff        = (uint)0;
            var  idata_limit = (uint)0;
            uint i           = 0;
            var  pal_len     = (uint)0;
            var  first       = 1;
            var  k           = 0;
            var  interlace   = 0;
            var  color       = 0;
            var  is_iphone   = 0;
            var  s           = z.s;

            z.expanded = null;
            z.idata    = null;
            z._out_    = null;
            if (stbi__check_png_header(s) == 0)
            {
                return(0);
            }
            if (scan == STBI__SCAN_type)
            {
                return(1);
            }
            for (; ;)
            {
                var c = stbi__get_chunk_header(s);
                switch (c.type)
                {
                case ((uint)'C' << 24) + ((uint)'g' << 16) + ((uint)'B' << 8) + 'I':
                    is_iphone = 1;
                    stbi__skip(s, (int)c.length);
                    break;

                case ((uint)'I' << 24) + ((uint)'H' << 16) + ((uint)'D' << 8) + 'R':
                {
                    var comp   = 0;
                    var filter = 0;
                    if (first == 0)
                    {
                        return(stbi__err("multiple IHDR"));
                    }
                    first = 0;
                    if (c.length != 13)
                    {
                        return(stbi__err("bad IHDR len"));
                    }
                    s.img_x = stbi__get32be(s);
                    if (s.img_x > 1 << 24)
                    {
                        return(stbi__err("too large"));
                    }
                    s.img_y = stbi__get32be(s);
                    if (s.img_y > 1 << 24)
                    {
                        return(stbi__err("too large"));
                    }
                    z.depth = stbi__get8(s);
                    if (z.depth != 1 && z.depth != 2 && z.depth != 4 && z.depth != 8 && z.depth != 16)
                    {
                        return(stbi__err("1/2/4/8/16-bit only"));
                    }
                    color = stbi__get8(s);
                    if (color > 6)
                    {
                        return(stbi__err("bad ctype"));
                    }
                    if (color == 3 && z.depth == 16)
                    {
                        return(stbi__err("bad ctype"));
                    }
                    if (color == 3)
                    {
                        pal_img_n = 3;
                    }
                    else if ((color & 1) != 0)
                    {
                        return(stbi__err("bad ctype"));
                    }
                    comp = stbi__get8(s);
                    if (comp != 0)
                    {
                        return(stbi__err("bad comp method"));
                    }
                    filter = stbi__get8(s);
                    if (filter != 0)
                    {
                        return(stbi__err("bad filter method"));
                    }
                    interlace = stbi__get8(s);
                    if (interlace > 1)
                    {
                        return(stbi__err("bad interlace method"));
                    }
                    if (s.img_x == 0 || s.img_y == 0)
                    {
                        return(stbi__err("0-pixel image"));
                    }
                    if (pal_img_n == 0)
                    {
                        s.img_n = ((color & 2) != 0 ? 3 : 1) + ((color & 4) != 0 ? 1 : 0);
                        if ((1 << 30) / s.img_x / s.img_n < s.img_y)
                        {
                            return(stbi__err("too large"));
                        }
                        if (scan == STBI__SCAN_header)
                        {
                            return(1);
                        }
                    }
                    else
                    {
                        s.img_n = 1;
                        if ((1 << 30) / s.img_x / 4 < s.img_y)
                        {
                            return(stbi__err("too large"));
                        }
                    }

                    break;
                }

                case ((uint)'P' << 24) + ((uint)'L' << 16) + ((uint)'T' << 8) + 'E':
                {
                    if (first != 0)
                    {
                        return(stbi__err("first not IHDR"));
                    }
                    if (c.length > 256 * 3)
                    {
                        return(stbi__err("invalid PLTE"));
                    }
                    pal_len = c.length / 3;
                    if (pal_len * 3 != c.length)
                    {
                        return(stbi__err("invalid PLTE"));
                    }
                    for (i = (uint)0; i < pal_len; ++i)
                    {
                        palette[i * 4 + 0] = stbi__get8(s);
                        palette[i * 4 + 1] = stbi__get8(s);
                        palette[i * 4 + 2] = stbi__get8(s);
                        palette[i * 4 + 3] = 255;
                    }

                    break;
                }

                case ((uint)'t' << 24) + ((uint)'R' << 16) + ((uint)'N' << 8) + 'S':
                {
                    if (first != 0)
                    {
                        return(stbi__err("first not IHDR"));
                    }
                    if (z.idata != null)
                    {
                        return(stbi__err("tRNS after IDAT"));
                    }
                    if (pal_img_n != 0)
                    {
                        if (scan == STBI__SCAN_header)
                        {
                            s.img_n = 4;
                            return(1);
                        }

                        if (pal_len == 0)
                        {
                            return(stbi__err("tRNS before PLTE"));
                        }
                        if (c.length > pal_len)
                        {
                            return(stbi__err("bad tRNS len"));
                        }
                        pal_img_n = 4;
                        for (i = (uint)0; i < c.length; ++i)
                        {
                            palette[i * 4 + 3] = stbi__get8(s);
                        }
                    }
                    else
                    {
                        if ((s.img_n & 1) == 0)
                        {
                            return(stbi__err("tRNS with alpha"));
                        }
                        if (c.length != (uint)s.img_n * 2)
                        {
                            return(stbi__err("bad tRNS len"));
                        }
                        has_trans = 1;
                        if (z.depth == 16)
                        {
                            for (k = 0; k < s.img_n; ++k)
                            {
                                tc16[k] = (ushort)stbi__get16be(s);
                            }
                        }
                        else
                        {
                            for (k = 0; k < s.img_n; ++k)
                            {
                                tc[k] = (byte)((byte)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z.depth]);
                            }
                        }
                    }

                    break;
                }

                case ((uint)'I' << 24) + ((uint)'D' << 16) + ((uint)'A' << 8) + 'T':
                {
                    if (first != 0)
                    {
                        return(stbi__err("first not IHDR"));
                    }
                    if (pal_img_n != 0 && pal_len == 0)
                    {
                        return(stbi__err("no PLTE"));
                    }
                    if (scan == STBI__SCAN_header)
                    {
                        s.img_n = pal_img_n;
                        return(1);
                    }

                    if ((int)(ioff + c.length) < (int)ioff)
                    {
                        return(0);
                    }
                    if (ioff + c.length > idata_limit)
                    {
                        var   idata_limit_old = idata_limit;
                        byte *p;
                        if (idata_limit == 0)
                        {
                            idata_limit = c.length > 4096 ? c.length : 4096;
                        }
                        while (ioff + c.length > idata_limit)
                        {
                            idata_limit *= 2;
                        }
                        p = (byte *)CRuntime.realloc(z.idata, (ulong)idata_limit);
                        if (p == null)
                        {
                            return(stbi__err("outofmem"));
                        }
                        z.idata = p;
                    }

                    if (stbi__getn(s, z.idata + ioff, (int)c.length) == 0)
                    {
                        return(stbi__err("outofdata"));
                    }
                    ioff += c.length;
                    break;
                }

                case ((uint)'I' << 24) + ((uint)'E' << 16) + ((uint)'N' << 8) + 'D':
                {
                    uint raw_len = 0;
                    uint bpl     = 0;
                    if (first != 0)
                    {
                        return(stbi__err("first not IHDR"));
                    }
                    if (scan != STBI__SCAN_load)
                    {
                        return(1);
                    }
                    if (z.idata == null)
                    {
                        return(stbi__err("no IDAT"));
                    }
                    bpl        = (uint)((s.img_x * z.depth + 7) / 8);
                    raw_len    = (uint)(bpl * s.img_y * s.img_n + s.img_y);
                    z.expanded = (byte *)stbi_zlib_decode_malloc_guesssize_headerflag((sbyte *)z.idata, (int)ioff,
                                                                                      (int)raw_len, (int *)&raw_len, is_iphone != 0 ? 0 : 1);
                    if (z.expanded == null)
                    {
                        return(0);
                    }
                    CRuntime.free(z.idata);
                    z.idata = null;
                    if (req_comp == s.img_n + 1 && req_comp != 3 && pal_img_n == 0 || has_trans != 0)
                    {
                        s.img_out_n = s.img_n + 1;
                    }
                    else
                    {
                        s.img_out_n = s.img_n;
                    }
                    if (stbi__create_png_image(z, z.expanded, raw_len, s.img_out_n, z.depth, color, interlace) == 0)
                    {
                        return(0);
                    }
                    if (has_trans != 0)
                    {
                        if (z.depth == 16)
                        {
                            if (stbi__compute_transparency16(z, tc16, s.img_out_n) == 0)
                            {
                                return(0);
                            }
                        }
                        else
                        {
                            if (stbi__compute_transparency(z, tc, s.img_out_n) == 0)
                            {
                                return(0);
                            }
                        }
                    }

                    if (is_iphone != 0 && stbi__de_iphone_flag != 0 && s.img_out_n > 2)
                    {
                        stbi__de_iphone(z);
                    }
                    if (pal_img_n != 0)
                    {
                        s.img_n     = pal_img_n;
                        s.img_out_n = pal_img_n;
                        if (req_comp >= 3)
                        {
                            s.img_out_n = req_comp;
                        }
                        if (stbi__expand_png_palette(z, palette, (int)pal_len, s.img_out_n) == 0)
                        {
                            return(0);
                        }
                    }
                    else if (has_trans != 0)
                    {
                        ++s.img_n;
                    }

                    CRuntime.free(z.expanded);
                    z.expanded = null;
                    return(1);
                }

                default:
                    if (first != 0)
                    {
                        return(stbi__err("first not IHDR"));
                    }
                    if ((c.type & (1 << 29)) == 0)
                    {
                        var invalid_chunk = c.type + " PNG chunk not known";
                        return(stbi__err(invalid_chunk));
                    }

                    stbi__skip(s, (int)c.length);
                    break;
                }

                stbi__get32be(s);
            }
        }