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);
        }
        protected unsafe virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_gif != null)
                {
                    if (_gif._out_ != null)
                    {
                        CRuntime.free(_gif._out_);
                        _gif._out_ = null;
                    }

                    if (_gif.history != null)
                    {
                        CRuntime.free(_gif.history);
                        _gif.history = null;
                    }

                    if (_gif.background != null)
                    {
                        CRuntime.free(_gif.background);
                        _gif.background = null;
                    }

                    _gif = null;
                }
            }
        }
Пример #3
0
        public static void *stbi__gif_load(stbi__context s, int *x, int *y, int *comp, int req_comp,
                                           stbi__result_info *ri)
        {
            byte *u = null;
            var   g = new stbi__gif();

            u = stbi__gif_load_next(s, g, comp, req_comp, null);

            if (u != null)
            {
                *x = g.w;
                *y = g.h;
                if (req_comp != 0 && req_comp != 4)
                {
                    u = stbi__convert_format(u, 4, req_comp, (uint)g.w, (uint)g.h);
                }
            }
            else if (g._out_ != null)
            {
                CRuntime.free(g._out_);
            }

            CRuntime.free(g.history);
            CRuntime.free(g.background);
            return(u);
        }
        public static void *stbi__do_png(stbi__png p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
        {
            void *result = null;

            if (req_comp < 0 || req_comp > 4)
            {
                return((byte *)(ulong)(stbi__err("bad req_comp") != 0 ? 0 : 0));
            }
            if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp) != 0)
            {
                if (p.depth <= 8)
                {
                    ri->bits_per_channel = 8;
                }
                else if (p.depth == 16)
                {
                    ri->bits_per_channel = 16;
                }
                else
                {
                    return((byte *)(ulong)(stbi__err("bad bits_per_channel") != 0 ? 0 : 0));
                }
                result  = p._out_;
                p._out_ = null;
                if (req_comp != 0 && req_comp != p.s.img_out_n)
                {
                    if (ri->bits_per_channel == 8)
                    {
                        result = stbi__convert_format((byte *)result, p.s.img_out_n, req_comp, p.s.img_x, p.s.img_y);
                    }
                    else
                    {
                        result = stbi__convert_format16((ushort *)result, p.s.img_out_n, req_comp, p.s.img_x,
                                                        p.s.img_y);
                    }
                    p.s.img_out_n = req_comp;
                    if (result == null)
                    {
                        return(result);
                    }
                }

                *x = (int)p.s.img_x;
                *y = (int)p.s.img_y;
                if (n != null)
                {
                    *n = p.s.img_n;
                }
            }

            CRuntime.free(p._out_);
            p._out_ = null;
            CRuntime.free(p.expanded);
            p.expanded = null;
            CRuntime.free(p.idata);
            p.idata = null;
            return(result);
        }
Пример #5
0
 public static void *stbi__load_gif_main_outofmem(stbi__gif g, byte *_out_, int **delays)
 {
     CRuntime.free(g._out_);
     CRuntime.free(g.history);
     CRuntime.free(g.background);
     if (_out_ != null)
     {
         CRuntime.free(_out_);
     }
     if (delays != null && *delays != null)
     {
         CRuntime.free(*delays);
     }
     return((byte *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
 }
        public static float *stbi__ldr_to_hdr(byte *data, int x, int y, int comp)
        {
            var    i = 0;
            var    k = 0;
            var    n = 0;
            float *output;

            if (data == null)
            {
                return(null);
            }
            output = (float *)stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
            if (output == null)
            {
                CRuntime.free(data);
                return((float *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
            }

            if ((comp & 1) != 0)
            {
                n = comp;
            }
            else
            {
                n = comp - 1;
            }
            for (i = 0; i < x * y; ++i)
            {
                for (k = 0; k < n; ++k)
                {
                    output[i * comp + k] =
                        (float)(CRuntime.pow(data[i * comp + k] / 255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
                }
            }

            if (n < comp)
            {
                for (i = 0; i < x * y; ++i)
                {
                    output[i * comp + n] = data[i * comp + n] / 255.0f;
                }
            }

            CRuntime.free(data);
            return(output);
        }
        public static ushort *stbi__convert_8_to_16(byte *orig, int w, int h, int channels)
        {
            var     i       = 0;
            var     img_len = w * h * channels;
            ushort *enlarged;

            enlarged = (ushort *)stbi__malloc((ulong)(img_len * 2));
            if (enlarged == null)
            {
                return((ushort *)(byte *)(ulong)(stbi__err("outofmem") != 0 ? (byte *)null : null));
            }
            for (i = 0; i < img_len; ++i)
            {
                enlarged[i] = (ushort)((orig[i] << 8) + orig[i]);
            }
            CRuntime.free(orig);
            return(enlarged);
        }
        public static byte *stbi__convert_16_to_8(ushort *orig, int w, int h, int channels)
        {
            var   i       = 0;
            var   img_len = w * h * channels;
            byte *reduced;

            reduced = (byte *)stbi__malloc((ulong)img_len);
            if (reduced == null)
            {
                return((byte *)(ulong)(stbi__err("outofmem") != 0 ? (byte *)null : null));
            }
            for (i = 0; i < img_len; ++i)
            {
                reduced[i] = (byte)((orig[i] >> 8) & 0xFF);
            }
            CRuntime.free(orig);
            return(reduced);
        }
        public static int stbi__expand_png_palette(stbi__png a, byte *palette, int len, int pal_img_n)
        {
            uint  i           = 0;
            var   pixel_count = a.s.img_x * a.s.img_y;
            byte *p;
            byte *temp_out;
            var   orig = a._out_;

            p = (byte *)stbi__malloc_mad2((int)pixel_count, pal_img_n, 0);
            if (p == null)
            {
                return(stbi__err("outofmem"));
            }
            temp_out = p;
            if (pal_img_n == 3)
            {
                for (i = (uint)0; i < pixel_count; ++i)
                {
                    var n = orig[i] * 4;
                    p[0] = palette[n];
                    p[1] = palette[n + 1];
                    p[2] = palette[n + 2];
                    p   += 3;
                }
            }
            else
            {
                for (i = (uint)0; i < pixel_count; ++i)
                {
                    var n = orig[i] * 4;
                    p[0] = palette[n];
                    p[1] = palette[n + 1];
                    p[2] = palette[n + 2];
                    p[3] = palette[n + 3];
                    p   += 4;
                }
            }

            CRuntime.free(a._out_);
            a._out_ = temp_out;
            return(1);
        }
Пример #10
0
            public void Dispose()
            {
                if (pal != null)
                {
                    CRuntime.free(pal);
                    pal = null;
                }

                if (lpal != null)
                {
                    CRuntime.free(lpal);
                    lpal = null;
                }

                if (codes != null)
                {
                    CRuntime.free(codes);
                    codes = null;
                }
            }
Пример #11
0
        public static unsafe ImageResultFloat FromStream(Stream stream, ColorComponents requiredComponents = ColorComponents.Default)
        {
            float *result = null;

            try
            {
                int x, y, comp;

                var context = new StbImage.stbi__context(stream);

                result = StbImage.stbi__loadf_main(context, &x, &y, &comp, (int)requiredComponents);

                return(FromResult(result, x, y, (ColorComponents)comp, requiredComponents));
            }
            finally
            {
                if (result != null)
                {
                    CRuntime.free(result);
                }
            }
        }
Пример #12
0
        public static unsafe ImageResult FromStream(Stream stream,
                                                    ColorComponents requiredComponents = ColorComponents.Default)
        {
            byte *result = null;

            try
            {
                int x, y, comp;

                var context = new stbi__context(stream);

                result = stbi__load_and_postprocess_8bit(context, &x, &y, &comp, (int)requiredComponents);

                return(FromResult(result, x, y, (ColorComponents)comp, requiredComponents));
            }
            finally
            {
                if (result != null)
                {
                    CRuntime.free(result);
                }
            }
        }
Пример #13
0
        public static sbyte *stbi_zlib_decode_noheader_malloc(sbyte *buffer, int len, int *outlen)
        {
            var a = new stbi__zbuf();
            var p = (sbyte *)stbi__malloc((ulong)16384);

            if (p == null)
            {
                return(null);
            }
            a.zbuffer     = (byte *)buffer;
            a.zbuffer_end = (byte *)buffer + len;
            if (stbi__do_zlib(&a, p, 16384, 1, 0) != 0)
            {
                if (outlen != null)
                {
                    *outlen = (int)(a.zout - a.zout_start);
                }
                return(a.zout_start);
            }

            CRuntime.free(a.zout_start);
            return(null);
        }
Пример #14
0
        public static sbyte *stbi_zlib_decode_malloc_guesssize(sbyte *buffer, int len, int initial_size, int *outlen)
        {
            var a = new stbi__zbuf();
            var p = (sbyte *)stbi__malloc((ulong)initial_size);

            if (p == null)
            {
                return(null);
            }
            a.zbuffer     = (byte *)buffer;
            a.zbuffer_end = (byte *)buffer + len;
            if (stbi__do_zlib(&a, p, initial_size, 1, 1) != 0)
            {
                if (outlen != null)
                {
                    *outlen = (int)(a.zout - a.zout_start);
                }
                return(a.zout_start);
            }

            CRuntime.free(a.zout_start);
            return(null);
        }
Пример #15
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 byte *stbi__hdr_to_ldr(float *data, int x, int y, int comp)
        {
            var   i = 0;
            var   k = 0;
            var   n = 0;
            byte *output;

            if (data == null)
            {
                return(null);
            }
            output = (byte *)stbi__malloc_mad3(x, y, comp, 0);
            if (output == null)
            {
                CRuntime.free(data);
                return((byte *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
            }

            if ((comp & 1) != 0)
            {
                n = comp;
            }
            else
            {
                n = comp - 1;
            }
            for (i = 0; i < x * y; ++i)
            {
                for (k = 0; k < n; ++k)
                {
                    var z = (float)CRuntime.pow(data[i * comp + k] * stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 +
                            0.5f;
                    if (z < 0)
                    {
                        z = 0;
                    }
                    if (z > 255)
                    {
                        z = 255;
                    }
                    output[i * comp + k] = (byte)(int)z;
                }

                if (k < comp)
                {
                    var z = data[i * comp + k] * 255 + 0.5f;
                    if (z < 0)
                    {
                        z = 0;
                    }
                    if (z > 255)
                    {
                        z = 255;
                    }
                    output[i * comp + k] = (byte)(int)z;
                }
            }

            CRuntime.free(data);
            return(output);
        }
        public static float *stbi__hdr_load(stbi__context s, int *x, int *y, int *comp, int req_comp,
                                            stbi__result_info *ri)
        {
            var    buffer = stackalloc sbyte[1024];
            sbyte *token;
            var    valid  = 0;
            var    width  = 0;
            var    height = 0;
            byte * scanline;
            float *hdr_data;
            var    len   = 0;
            byte   count = 0;
            byte   value = 0;
            var    i     = 0;
            var    j     = 0;
            var    k     = 0;
            var    c1    = 0;
            var    c2    = 0;
            var    z     = 0;
            sbyte *headerToken;

            headerToken = stbi__hdr_gettoken(s, buffer);
            if (CRuntime.strcmp(headerToken, "#?RADIANCE") != 0 && CRuntime.strcmp(headerToken, "#?RGBE") != 0)
            {
                return((float *)(ulong)(stbi__err("not HDR") != 0 ? 0 : 0));
            }
            for (; ;)
            {
                token = stbi__hdr_gettoken(s, buffer);
                if (token[0] == 0)
                {
                    break;
                }
                if (CRuntime.strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0)
                {
                    valid = 1;
                }
            }

            if (valid == 0)
            {
                return((float *)(ulong)(stbi__err("unsupported format") != 0 ? 0 : 0));
            }
            token = stbi__hdr_gettoken(s, buffer);
            if (CRuntime.strncmp(token, "-Y ", 3) != 0)
            {
                return((float *)(ulong)(stbi__err("unsupported data layout") != 0 ? 0 : 0));
            }
            token += 3;
            height = (int)CRuntime.strtol(token, &token, 10);
            while (*token == 32)
            {
                ++token;
            }

            if (CRuntime.strncmp(token, "+X ", 3) != 0)
            {
                return((float *)(ulong)(stbi__err("unsupported data layout") != 0 ? 0 : 0));
            }
            token += 3;
            width  = (int)CRuntime.strtol(token, null, 10);
            if (height > 1 << 24)
            {
                return((float *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            if (width > 1 << 24)
            {
                return((float *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            *x = width;
            *y = height;
            if (comp != null)
            {
                *comp = 3;
            }
            if (req_comp == 0)
            {
                req_comp = 3;
            }
            if (stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0) == 0)
            {
                return((float *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            hdr_data = (float *)stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
            if (hdr_data == null)
            {
                return((float *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
            }

main_decode_loop:
            var enterMainDecode = false;

            if (enterMainDecode)
            {
                for (; j < height; ++j)
                {
                    for (; i < width; ++i)
                    {
                        var rgbe = stackalloc byte[4];
                        stbi__getn(s, rgbe, 4);
                        stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
                    }
                }

                goto finish;
            }

            if (width < 8 || width >= 32768)
            {
                i = j = 0;

                enterMainDecode = true;
                goto main_decode_loop;
            }

            scanline = null;
            for (j = 0; j < height; ++j)
            {
                c1  = stbi__get8(s);
                c2  = stbi__get8(s);
                len = stbi__get8(s);
                if (c1 != 2 || c2 != 2 || (len & 0x80) != 0)
                {
                    var rgbe = stackalloc byte[4];
                    rgbe[0] = (byte)c1;
                    rgbe[1] = (byte)c2;
                    rgbe[2] = (byte)len;
                    rgbe[3] = stbi__get8(s);
                    stbi__hdr_convert(hdr_data, rgbe, req_comp);
                    i = 1;
                    j = 0;
                    CRuntime.free(scanline);
                    goto main_decode_loop;
                }

                len <<= 8;
                len  |= stbi__get8(s);
                if (len != width)
                {
                    CRuntime.free(hdr_data);
                    CRuntime.free(scanline);
                    return((float *)(ulong)(stbi__err("invalid decoded scanline length") != 0 ? 0 : 0));
                }

                if (scanline == null)
                {
                    scanline = (byte *)stbi__malloc_mad2(width, 4, 0);
                    if (scanline == null)
                    {
                        CRuntime.free(hdr_data);
                        return((float *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
                    }
                }

                for (k = 0; k < 4; ++k)
                {
                    var nleft = 0;
                    i = 0;
                    while ((nleft = width - i) > 0)
                    {
                        count = stbi__get8(s);
                        if (count > 128)
                        {
                            value  = stbi__get8(s);
                            count -= 128;
                            if (count > nleft)
                            {
                                CRuntime.free(hdr_data);
                                CRuntime.free(scanline);
                                return((float *)(ulong)(stbi__err("corrupt") != 0 ? 0 : 0));
                            }

                            for (z = 0; z < count; ++z)
                            {
                                scanline[i++ *4 + k] = value;
                            }
                        }
                        else
                        {
                            if (count > nleft)
                            {
                                CRuntime.free(hdr_data);
                                CRuntime.free(scanline);
                                return((float *)(ulong)(stbi__err("corrupt") != 0 ? 0 : 0));
                            }

                            for (z = 0; z < count; ++z)
                            {
                                scanline[i++ *4 + k] = stbi__get8(s);
                            }
                        }
                    }
                }

                for (i = 0; i < width; ++i)
                {
                    stbi__hdr_convert(hdr_data + (j * width + i) * req_comp, scanline + i * 4, req_comp);
                }
            }

            if (scanline != null)
            {
                CRuntime.free(scanline);
            }

finish:
            return(hdr_data);
        }
        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);
            }
        }
Пример #19
0
        public static void *stbi__psd_load(stbi__context s, int *x, int *y, int *comp, int req_comp,
                                           stbi__result_info *ri, int bpc)
        {
            var   pixelCount   = 0;
            var   channelCount = 0;
            var   compression  = 0;
            var   channel      = 0;
            var   i            = 0;
            var   bitdepth     = 0;
            var   w            = 0;
            var   h            = 0;
            byte *_out_;

            if (stbi__get32be(s) != 0x38425053)
            {
                return((byte *)(ulong)(stbi__err("not PSD") != 0 ? 0 : 0));
            }
            if (stbi__get16be(s) != 1)
            {
                return((byte *)(ulong)(stbi__err("wrong version") != 0 ? 0 : 0));
            }
            stbi__skip(s, 6);
            channelCount = stbi__get16be(s);
            if (channelCount < 0 || channelCount > 16)
            {
                return((byte *)(ulong)(stbi__err("wrong channel count") != 0 ? 0 : 0));
            }
            h = (int)stbi__get32be(s);
            w = (int)stbi__get32be(s);
            if (h > 1 << 24)
            {
                return((byte *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            if (w > 1 << 24)
            {
                return((byte *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            bitdepth = stbi__get16be(s);
            if (bitdepth != 8 && bitdepth != 16)
            {
                return((byte *)(ulong)(stbi__err("unsupported bit depth") != 0 ? 0 : 0));
            }
            if (stbi__get16be(s) != 3)
            {
                return((byte *)(ulong)(stbi__err("wrong color format") != 0 ? 0 : 0));
            }
            stbi__skip(s, (int)stbi__get32be(s));
            stbi__skip(s, (int)stbi__get32be(s));
            stbi__skip(s, (int)stbi__get32be(s));
            compression = stbi__get16be(s);
            if (compression > 1)
            {
                return((byte *)(ulong)(stbi__err("bad compression") != 0 ? 0 : 0));
            }
            if (stbi__mad3sizes_valid(4, w, h, 0) == 0)
            {
                return((byte *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            if (compression == 0 && bitdepth == 16 && bpc == 16)
            {
                _out_ = (byte *)stbi__malloc_mad3(8, w, h, 0);
                ri->bits_per_channel = 16;
            }
            else
            {
                _out_ = (byte *)stbi__malloc((ulong)(4 * w * h));
            }

            if (_out_ == null)
            {
                return((byte *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
            }
            pixelCount = w * h;
            if (compression != 0)
            {
                stbi__skip(s, h * channelCount * 2);
                for (channel = 0; channel < 4; channel++)
                {
                    byte *p;
                    p = _out_ + channel;
                    if (channel >= channelCount)
                    {
                        for (i = 0; i < pixelCount; i++, p += 4)
                        {
                            *p = (byte)(channel == 3 ? 255 : 0);
                        }
                    }
                    else
                    {
                        if (stbi__psd_decode_rle(s, p, pixelCount) == 0)
                        {
                            CRuntime.free(_out_);
                            return((byte *)(ulong)(stbi__err("corrupt") != 0 ? 0 : 0));
                        }
                    }
                }
            }
            else
            {
                for (channel = 0; channel < 4; channel++)
                {
                    if (channel >= channelCount)
                    {
                        if (bitdepth == 16 && bpc == 16)
                        {
                            var q   = (ushort *)_out_ + channel;
                            var val = (ushort)(channel == 3 ? 65535 : 0);
                            for (i = 0; i < pixelCount; i++, q += 4)
                            {
                                *q = val;
                            }
                        }
                        else
                        {
                            var p   = _out_ + channel;
                            var val = (byte)(channel == 3 ? 255 : 0);
                            for (i = 0; i < pixelCount; i++, p += 4)
                            {
                                *p = val;
                            }
                        }
                    }
                    else
                    {
                        if (ri->bits_per_channel == 16)
                        {
                            var q = (ushort *)_out_ + channel;
                            for (i = 0; i < pixelCount; i++, q += 4)
                            {
                                *q = (ushort)stbi__get16be(s);
                            }
                        }
                        else
                        {
                            var p = _out_ + channel;
                            if (bitdepth == 16)
                            {
                                for (i = 0; i < pixelCount; i++, p += 4)
                                {
                                    *p = (byte)(stbi__get16be(s) >> 8);
                                }
                            }
                            else
                            {
                                for (i = 0; i < pixelCount; i++, p += 4)
                                {
                                    *p = stbi__get8(s);
                                }
                            }
                        }
                    }
                }
            }

            if (channelCount >= 4)
            {
                if (ri->bits_per_channel == 16)
                {
                    for (i = 0; i < w * h; ++i)
                    {
                        var pixel = (ushort *)_out_ + 4 * i;
                        if (pixel[3] != 0 && pixel[3] != 65535)
                        {
                            var a     = pixel[3] / 65535.0f;
                            var ra    = 1.0f / a;
                            var inv_a = 65535.0f * (1 - ra);
                            pixel[0] = (ushort)(pixel[0] * ra + inv_a);
                            pixel[1] = (ushort)(pixel[1] * ra + inv_a);
                            pixel[2] = (ushort)(pixel[2] * ra + inv_a);
                        }
                    }
                }
                else
                {
                    for (i = 0; i < w * h; ++i)
                    {
                        var pixel = _out_ + 4 * i;
                        if (pixel[3] != 0 && pixel[3] != 255)
                        {
                            var a     = pixel[3] / 255.0f;
                            var ra    = 1.0f / a;
                            var inv_a = 255.0f * (1 - ra);
                            pixel[0] = (byte)(pixel[0] * ra + inv_a);
                            pixel[1] = (byte)(pixel[1] * ra + inv_a);
                            pixel[2] = (byte)(pixel[2] * ra + inv_a);
                        }
                    }
                }
            }

            if (req_comp != 0 && req_comp != 4)
            {
                if (ri->bits_per_channel == 16)
                {
                    _out_ = (byte *)stbi__convert_format16((ushort *)_out_, 4, req_comp, (uint)w, (uint)h);
                }
                else
                {
                    _out_ = stbi__convert_format(_out_, 4, req_comp, (uint)w, (uint)h);
                }
                if (_out_ == null)
                {
                    return(_out_);
                }
            }

            if (comp != null)
            {
                *comp = 4;
            }
            *y = h;
            *x = w;
            return(_out_);
        }
Пример #20
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_);
        }
        public static void *stbi__tga_load(stbi__context s, int *x, int *y, int *comp, int req_comp,
                                           stbi__result_info *ri)
        {
            int   tga_offset         = stbi__get8(s);
            int   tga_indexed        = stbi__get8(s);
            int   tga_image_type     = stbi__get8(s);
            var   tga_is_RLE         = 0;
            var   tga_palette_start  = stbi__get16le(s);
            var   tga_palette_len    = stbi__get16le(s);
            int   tga_palette_bits   = stbi__get8(s);
            var   tga_x_origin       = stbi__get16le(s);
            var   tga_y_origin       = stbi__get16le(s);
            var   tga_width          = stbi__get16le(s);
            var   tga_height         = stbi__get16le(s);
            int   tga_bits_per_pixel = stbi__get8(s);
            var   tga_comp           = 0;
            var   tga_rgb16          = 0;
            int   tga_inverted       = stbi__get8(s);
            byte *tga_data;
            byte *tga_palette     = null;
            var   i               = 0;
            var   j               = 0;
            var   raw_data        = stackalloc byte[] { 0, 0, 0, 0 };
            var   RLE_count       = 0;
            var   RLE_repeating   = 0;
            var   read_next_pixel = 1;

            if (tga_height > 1 << 24)
            {
                return((byte *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            if (tga_width > 1 << 24)
            {
                return((byte *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            if (tga_image_type >= 8)
            {
                tga_image_type -= 8;
                tga_is_RLE      = 1;
            }

            tga_inverted = 1 - ((tga_inverted >> 5) & 1);
            if (tga_indexed != 0)
            {
                tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
            }
            else
            {
                tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, tga_image_type == 3 ? 1 : 0, &tga_rgb16);
            }
            if (tga_comp == 0)
            {
                return((byte *)(ulong)(stbi__err("bad format") != 0 ? 0 : 0));
            }
            *x = tga_width;
            *y = tga_height;
            if (comp != null)
            {
                *comp = tga_comp;
            }
            if (stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0) == 0)
            {
                return((byte *)(ulong)(stbi__err("too large") != 0 ? 0 : 0));
            }
            tga_data = (byte *)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
            if (tga_data == null)
            {
                return((byte *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
            }
            stbi__skip(s, tga_offset);
            if (tga_indexed == 0 && tga_is_RLE == 0 && tga_rgb16 == 0)
            {
                for (i = 0; i < tga_height; ++i)
                {
                    var row     = tga_inverted != 0 ? tga_height - i - 1 : i;
                    var tga_row = tga_data + row * tga_width * tga_comp;
                    stbi__getn(s, tga_row, tga_width * tga_comp);
                }
            }
            else
            {
                if (tga_indexed != 0)
                {
                    if (tga_palette_len == 0)
                    {
                        CRuntime.free(tga_data);
                        return((byte *)(ulong)(stbi__err("bad palette") != 0 ? 0 : 0));
                    }

                    stbi__skip(s, tga_palette_start);
                    tga_palette = (byte *)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
                    if (tga_palette == null)
                    {
                        CRuntime.free(tga_data);
                        return((byte *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
                    }

                    if (tga_rgb16 != 0)
                    {
                        var pal_entry = tga_palette;
                        for (i = 0; i < tga_palette_len; ++i)
                        {
                            stbi__tga_read_rgb16(s, pal_entry);
                            pal_entry += tga_comp;
                        }
                    }
                    else if (stbi__getn(s, tga_palette, tga_palette_len * tga_comp) == 0)
                    {
                        CRuntime.free(tga_data);
                        CRuntime.free(tga_palette);
                        return((byte *)(ulong)(stbi__err("bad palette") != 0 ? 0 : 0));
                    }
                }

                for (i = 0; i < tga_width * tga_height; ++i)
                {
                    if (tga_is_RLE != 0)
                    {
                        if (RLE_count == 0)
                        {
                            int RLE_cmd = stbi__get8(s);
                            RLE_count       = 1 + (RLE_cmd & 127);
                            RLE_repeating   = RLE_cmd >> 7;
                            read_next_pixel = 1;
                        }
                        else if (RLE_repeating == 0)
                        {
                            read_next_pixel = 1;
                        }
                    }
                    else
                    {
                        read_next_pixel = 1;
                    }

                    if (read_next_pixel != 0)
                    {
                        if (tga_indexed != 0)
                        {
                            var pal_idx = tga_bits_per_pixel == 8 ? stbi__get8(s) : stbi__get16le(s);
                            if (pal_idx >= tga_palette_len)
                            {
                                pal_idx = 0;
                            }

                            pal_idx *= tga_comp;
                            for (j = 0; j < tga_comp; ++j)
                            {
                                raw_data[j] = tga_palette[pal_idx + j];
                            }
                        }
                        else if (tga_rgb16 != 0)
                        {
                            stbi__tga_read_rgb16(s, raw_data);
                        }
                        else
                        {
                            for (j = 0; j < tga_comp; ++j)
                            {
                                raw_data[j] = stbi__get8(s);
                            }
                        }

                        read_next_pixel = 0;
                    }

                    for (j = 0; j < tga_comp; ++j)
                    {
                        tga_data[i * tga_comp + j] = raw_data[j];
                    }

                    --RLE_count;
                }

                if (tga_inverted != 0)
                {
                    for (j = 0; j * 2 < tga_height; ++j)
                    {
                        var index1 = j * tga_width * tga_comp;
                        var index2 = (tga_height - 1 - j) * tga_width * tga_comp;
                        for (i = tga_width * tga_comp; i > 0; --i)
                        {
                            var temp = tga_data[index1];
                            tga_data[index1] = tga_data[index2];
                            tga_data[index2] = temp;
                            ++index1;
                            ++index2;
                        }
                    }
                }

                if (tga_palette != null)
                {
                    CRuntime.free(tga_palette);
                }
            }

            if (tga_comp >= 3 && tga_rgb16 == 0)
            {
                var tga_pixel = tga_data;
                for (i = 0; i < tga_width * tga_height; ++i)
                {
                    var temp = tga_pixel[0];
                    tga_pixel[0] = tga_pixel[2];
                    tga_pixel[2] = temp;
                    tga_pixel   += tga_comp;
                }
            }

            if (req_comp != 0 && req_comp != tga_comp)
            {
                tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, (uint)tga_width, (uint)tga_height);
            }
            tga_palette_start = tga_palette_len = tga_palette_bits = tga_x_origin = tga_y_origin = 0;
            return(tga_data);
        }
        public static ushort *stbi__convert_format16(ushort *data, int img_n, int req_comp, uint x, uint y)
        {
            var     i = 0;
            var     j = 0;
            ushort *good;

            if (req_comp == img_n)
            {
                return(data);
            }
            good = (ushort *)stbi__malloc((ulong)(req_comp * x * y * 2));
            if (good == null)
            {
                CRuntime.free(data);
                return((ushort *)(byte *)(ulong)(stbi__err("outofmem") != 0 ? (byte *)null : null));
            }

            for (j = 0; j < (int)y; ++j)
            {
                var src  = data + j * x * img_n;
                var dest = good + j * x * req_comp;
                switch (img_n * 8 + req_comp)
                {
                case 1 * 8 + 2:
                    for (i = (int)(x - 1); i >= 0; --i, src += 1, dest += 2)
                    {
                        dest[0] = src[0];
                        dest[1] = 0xffff;
                    }

                    break;

                case 1 * 8 + 3:
                    for (i = (int)(x - 1); i >= 0; --i, src += 1, dest += 3)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                    }
                    break;

                case 1 * 8 + 4:
                    for (i = (int)(x - 1); i >= 0; --i, src += 1, dest += 4)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                        dest[3] = 0xffff;
                    }

                    break;

                case 2 * 8 + 1:
                    for (i = (int)(x - 1); i >= 0; --i, src += 2, dest += 1)
                    {
                        dest[0] = src[0];
                    }
                    break;

                case 2 * 8 + 3:
                    for (i = (int)(x - 1); i >= 0; --i, src += 2, dest += 3)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                    }
                    break;

                case 2 * 8 + 4:
                    for (i = (int)(x - 1); i >= 0; --i, src += 2, dest += 4)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                        dest[3] = src[1];
                    }

                    break;

                case 3 * 8 + 4:
                    for (i = (int)(x - 1); i >= 0; --i, src += 3, dest += 4)
                    {
                        dest[0] = src[0];
                        dest[1] = src[1];
                        dest[2] = src[2];
                        dest[3] = 0xffff;
                    }

                    break;

                case 3 * 8 + 1:
                    for (i = (int)(x - 1); i >= 0; --i, src += 3, dest += 1)
                    {
                        dest[0] = stbi__compute_y_16(src[0], src[1], src[2]);
                    }
                    break;

                case 3 * 8 + 2:
                    for (i = (int)(x - 1); i >= 0; --i, src += 3, dest += 2)
                    {
                        dest[0] = stbi__compute_y_16(src[0], src[1], src[2]);
                        dest[1] = 0xffff;
                    }

                    break;

                case 4 * 8 + 1:
                    for (i = (int)(x - 1); i >= 0; --i, src += 4, dest += 1)
                    {
                        dest[0] = stbi__compute_y_16(src[0], src[1], src[2]);
                    }
                    break;

                case 4 * 8 + 2:
                    for (i = (int)(x - 1); i >= 0; --i, src += 4, dest += 2)
                    {
                        dest[0] = stbi__compute_y_16(src[0], src[1], src[2]);
                        dest[1] = src[3];
                    }

                    break;

                case 4 * 8 + 3:
                    for (i = (int)(x - 1); i >= 0; --i, src += 4, dest += 3)
                    {
                        dest[0] = src[0];
                        dest[1] = src[1];
                        dest[2] = src[2];
                    }

                    break;

                default:
                    return((ushort *)(byte *)(ulong)(stbi__err("0") != 0 ? (byte *)null : null));
                }
            }

            CRuntime.free(data);
            return(good);
        }
        public static byte *stbi__convert_format(byte *data, int img_n, int req_comp, uint x, uint y)
        {
            var   i = 0;
            var   j = 0;
            byte *good;

            if (req_comp == img_n)
            {
                return(data);
            }
            good = (byte *)stbi__malloc_mad3(req_comp, (int)x, (int)y, 0);
            if (good == null)
            {
                CRuntime.free(data);
                return((byte *)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0));
            }

            for (j = 0; j < (int)y; ++j)
            {
                var src  = data + j * x * img_n;
                var dest = good + j * x * req_comp;
                switch (img_n * 8 + req_comp)
                {
                case 1 * 8 + 2:
                    for (i = (int)(x - 1); i >= 0; --i, src += 1, dest += 2)
                    {
                        dest[0] = src[0];
                        dest[1] = 255;
                    }

                    break;

                case 1 * 8 + 3:
                    for (i = (int)(x - 1); i >= 0; --i, src += 1, dest += 3)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                    }

                    break;

                case 1 * 8 + 4:
                    for (i = (int)(x - 1); i >= 0; --i, src += 1, dest += 4)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                        dest[3] = 255;
                    }

                    break;

                case 2 * 8 + 1:
                    for (i = (int)(x - 1); i >= 0; --i, src += 2, dest += 1)
                    {
                        dest[0] = src[0];
                    }

                    break;

                case 2 * 8 + 3:
                    for (i = (int)(x - 1); i >= 0; --i, src += 2, dest += 3)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                    }

                    break;

                case 2 * 8 + 4:
                    for (i = (int)(x - 1); i >= 0; --i, src += 2, dest += 4)
                    {
                        dest[0] = dest[1] = dest[2] = src[0];
                        dest[3] = src[1];
                    }

                    break;

                case 3 * 8 + 4:
                    for (i = (int)(x - 1); i >= 0; --i, src += 3, dest += 4)
                    {
                        dest[0] = src[0];
                        dest[1] = src[1];
                        dest[2] = src[2];
                        dest[3] = 255;
                    }

                    break;

                case 3 * 8 + 1:
                    for (i = (int)(x - 1); i >= 0; --i, src += 3, dest += 1)
                    {
                        dest[0] = stbi__compute_y(src[0], src[1], src[2]);
                    }

                    break;

                case 3 * 8 + 2:
                    for (i = (int)(x - 1); i >= 0; --i, src += 3, dest += 2)
                    {
                        dest[0] = stbi__compute_y(src[0], src[1], src[2]);
                        dest[1] = 255;
                    }

                    break;

                case 4 * 8 + 1:
                    for (i = (int)(x - 1); i >= 0; --i, src += 4, dest += 1)
                    {
                        dest[0] = stbi__compute_y(src[0], src[1], src[2]);
                    }

                    break;

                case 4 * 8 + 2:
                    for (i = (int)(x - 1); i >= 0; --i, src += 4, dest += 2)
                    {
                        dest[0] = stbi__compute_y(src[0], src[1], src[2]);
                        dest[1] = src[3];
                    }

                    break;

                case 4 * 8 + 3:
                    for (i = (int)(x - 1); i >= 0; --i, src += 4, dest += 3)
                    {
                        dest[0] = src[0];
                        dest[1] = src[1];
                        dest[2] = src[2];
                    }

                    break;

                default:
                    ;
                    CRuntime.free(data);
                    CRuntime.free(good);
                    return((byte *)(ulong)(stbi__err("unsupported") != 0 ? 0 : 0));
                }
            }

            CRuntime.free(data);
            return(good);
        }