Files
Misaki.HighPerformance/Misaki.HighPerformance.Image/StbImage.Generated.Gif.cs
Misaki 1fee890329 Refactor core APIs, fix bugs, and improve safety
- Make image result/info structs readonly; improve error handling and memory safety in image library
- Introduce IJobScheduler interface; move job scheduling docs to interface
- Remove "index 0 invalid" convention from slot/sparse maps; fix Count logic
- Add Owner<T> for disposable value types in low-level utilities
- Improve ObjectPool<T> thread safety and logic
- Change List<T>.RemoveAndSwapBack to return bool
- Remove unsafe methods from generated math types; add debug range checks
- Update benchmarks and enable collection checks in tests
- Improve documentation, comments, and error messages
- Bump assembly versions across all projects
2025-12-21 16:08:10 +09:00

681 lines
22 KiB
C#

// Generated by Sichem at 12/24/2021 8:28:15 PM
using Misaki.HighPerformance.Image.Runtime;
using System.Runtime.InteropServices;
namespace Misaki.HighPerformance.Image
{
public unsafe partial class StbImage
{
public static int stbi__gif_test(stbi__context s)
{
var r = stbi__gif_test_raw(s);
stbi__rewind(s);
return r;
}
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__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__gif_info(stbi__context s, int* x, int* y, int* comp)
{
return stbi__gif_info_raw(s, x, y, comp);
}
public static int stbi__gif_test_raw(stbi__context s)
{
var sz = 0;
if (stbi__get8(s) != 71 || stbi__get8(s) != 73 || stbi__get8(s) != 70 || stbi__get8(s) != 56)
{
return 0;
}
sz = stbi__get8(s);
if (sz != 57 && sz != 55)
{
return 0;
}
if (stbi__get8(s) != 97)
{
return 0;
}
return 1;
}
public static void stbi__gif_parse_colortable(stbi__context s, byte[][] pal, int num_entries, int transp)
{
var i = 0;
for (i = 0; i < num_entries; ++i)
{
pal[i][2] = stbi__get8(s);
pal[i][1] = stbi__get8(s);
pal[i][0] = stbi__get8(s);
pal[i][3] = (byte)(transp == i ? 0 : 255);
}
}
public static int stbi__gif_header(stbi__context s, stbi__gif g, int* comp, int is_info)
{
byte version = 0;
if (stbi__get8(s) != 71 || stbi__get8(s) != 73 || stbi__get8(s) != 70 || stbi__get8(s) != 56)
{
return stbi__err("not GIF");
}
version = stbi__get8(s);
if (version != 55 && version != 57)
{
return stbi__err("not GIF");
}
if (stbi__get8(s) != 97)
{
return stbi__err("not GIF");
}
stbi__g_failure_reason = "";
g.w = stbi__get16le(s);
g.h = stbi__get16le(s);
g.flags = stbi__get8(s);
g.bgindex = stbi__get8(s);
g.ratio = stbi__get8(s);
g.transparent = -1;
if (g.w > 1 << 24)
{
return stbi__err("too large");
}
if (g.h > 1 << 24)
{
return stbi__err("too large");
}
if (comp != null)
{
*comp = 4;
}
if (is_info != 0)
{
return 1;
}
if ((g.flags & 0x80) != 0)
{
stbi__gif_parse_colortable(s, g.pal, 2 << (g.flags & 7), -1);
}
return 1;
}
public static int stbi__gif_info_raw(stbi__context s, int* x, int* y, int* comp)
{
var g = new stbi__gif();
if (g == null)
{
return stbi__err("outofmem");
}
if (stbi__gif_header(s, g, comp, 1) == 0)
{
stbi__rewind(s);
return 0;
}
if (x != null)
{
*x = g.w;
}
if (y != null)
{
*y = g.h;
}
return 1;
}
public static void stbi__out_gif_code(stbi__gif g, ushort code)
{
byte* p;
var idx = 0;
if (g.codes[code].prefix >= 0)
{
stbi__out_gif_code(g, (ushort)g.codes[code].prefix);
}
if (g.cur_y >= g.max_y)
{
return;
}
idx = g.cur_x + g.cur_y;
p = &g._out_[idx];
g.history[idx / 4] = 1;
var c = g.color_table[g.codes[code].suffix];
if (c[3] > 128)
{
p[0] = c[2];
p[1] = c[1];
p[2] = c[0];
p[3] = c[3];
}
g.cur_x += 4;
if (g.cur_x >= g.max_x)
{
g.cur_x = g.start_x;
g.cur_y += g.step;
while (g.cur_y >= g.max_y && g.parse > 0)
{
g.step = (1 << g.parse) * g.line_size;
g.cur_y = g.start_y + (g.step >> 1);
--g.parse;
}
}
}
public static byte* stbi__process_gif_raster(stbi__context s, stbi__gif g)
{
byte lzw_cs = 0;
var len = 0;
var init_code = 0;
uint first = 0;
var codesize = 0;
var codemask = 0;
var avail = 0;
var oldcode = 0;
var bits = 0;
var valid_bits = 0;
var clear = 0;
stbi__gif_lzw* p;
lzw_cs = stbi__get8(s);
if (lzw_cs > 12)
{
return null;
}
clear = 1 << lzw_cs;
first = 1;
codesize = lzw_cs + 1;
codemask = (1 << codesize) - 1;
bits = 0;
valid_bits = 0;
for (init_code = 0; init_code < clear; init_code++)
{
g.codes[init_code].prefix = -1;
g.codes[init_code].first = (byte)init_code;
g.codes[init_code].suffix = (byte)init_code;
}
avail = clear + 2;
oldcode = -1;
len = 0;
for (; ; )
{
if (valid_bits < codesize)
{
if (len == 0)
{
len = stbi__get8(s);
if (len == 0)
{
return g._out_;
}
}
--len;
bits |= stbi__get8(s) << valid_bits;
valid_bits += 8;
}
else
{
var code = bits & codemask;
bits >>= codesize;
valid_bits -= codesize;
if (code == clear)
{
codesize = lzw_cs + 1;
codemask = (1 << codesize) - 1;
avail = clear + 2;
oldcode = -1;
first = 0;
}
else if (code == clear + 1)
{
stbi__skip(s, len);
while ((len = stbi__get8(s)) > 0)
{
stbi__skip(s, len);
}
return g._out_;
}
else if (code <= avail)
{
if (first != 0)
{
return (byte*)(ulong)(stbi__err("no clear code") != 0 ? 0 : 0);
}
if (oldcode >= 0)
{
fixed (stbi__gif_lzw* p2 = &g.codes[avail++])
{
p = p2;
if (avail > 8192)
{
return (byte*)(ulong)(stbi__err("too many codes") != 0 ? 0 : 0);
}
p->prefix = (short)oldcode;
p->first = g.codes[oldcode].first;
p->suffix = code == avail ? p->first : g.codes[code].first;
}
}
else if (code == avail)
{
return (byte*)(ulong)(stbi__err("illegal code in raster") != 0 ? 0 : 0);
}
stbi__out_gif_code(g, (ushort)code);
if ((avail & codemask) == 0 && avail <= 0x0FFF)
{
codesize++;
codemask = (1 << codesize) - 1;
}
oldcode = code;
}
else
{
return (byte*)(ulong)(stbi__err("illegal code in raster") != 0 ? 0 : 0);
}
}
}
}
public static byte* stbi__gif_load_next(stbi__context s, stbi__gif g, int* comp, int req_comp, byte* two_back)
{
var dispose = 0;
var first_frame = 0;
var pi = 0;
var pcount = 0;
first_frame = 0;
if (g._out_ == null)
{
if (stbi__gif_header(s, g, comp, 0) == 0)
{
return null;
}
if (stbi__mad3sizes_valid(4, g.w, g.h, 0) == 0)
{
return (byte*)(ulong)(stbi__err("too large") != 0 ? 0 : 0);
}
pcount = g.w * g.h;
g._out_ = (byte*)stbi__malloc((ulong)(4 * pcount));
g.background = (byte*)stbi__malloc((ulong)(4 * pcount));
g.history = (byte*)stbi__malloc((ulong)pcount);
if (g._out_ == null || g.background == null || g.history == null)
{
return (byte*)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0);
}
CRuntime.memset(g._out_, 0x00, (ulong)(4 * pcount));
CRuntime.memset(g.background, 0x00, (ulong)(4 * pcount));
CRuntime.memset(g.history, 0x00, (ulong)pcount);
first_frame = 1;
}
else
{
dispose = (g.eflags & 0x1C) >> 2;
pcount = g.w * g.h;
if (dispose == 3 && two_back == null)
{
dispose = 2;
}
if (dispose == 3)
{
for (pi = 0; pi < pcount; ++pi)
{
if (g.history[pi] != 0)
{
CRuntime.memcpy(&g._out_[pi * 4], &two_back[pi * 4], (ulong)4);
}
}
}
else if (dispose == 2)
{
for (pi = 0; pi < pcount; ++pi)
{
if (g.history[pi] != 0)
{
CRuntime.memcpy(&g._out_[pi * 4], &g.background[pi * 4], (ulong)4);
}
}
}
CRuntime.memcpy(g.background, g._out_, (ulong)(4 * g.w * g.h));
}
CRuntime.memset(g.history, 0x00, (ulong)(g.w * g.h));
for (; ; )
{
int tag = stbi__get8(s);
switch (tag)
{
case 0x2C:
{
var x = 0;
var y = 0;
var w = 0;
var h = 0;
byte* o;
x = stbi__get16le(s);
y = stbi__get16le(s);
w = stbi__get16le(s);
h = stbi__get16le(s);
if (x + w > g.w || y + h > g.h)
{
return (byte*)(ulong)(stbi__err("bad Image Descriptor") != 0 ? 0 : 0);
}
g.line_size = g.w * 4;
g.start_x = x * 4;
g.start_y = y * g.line_size;
g.max_x = g.start_x + w * 4;
g.max_y = g.start_y + h * g.line_size;
g.cur_x = g.start_x;
g.cur_y = g.start_y;
if (w == 0)
{
g.cur_y = g.max_y;
}
g.lflags = stbi__get8(s);
if ((g.lflags & 0x40) != 0)
{
g.step = 8 * g.line_size;
g.parse = 3;
}
else
{
g.step = g.line_size;
g.parse = 0;
}
if ((g.lflags & 0x80) != 0)
{
stbi__gif_parse_colortable(s, g.lpal, 2 << (g.lflags & 7),
(g.eflags & 0x01) != 0 ? g.transparent : -1);
g.color_table = g.lpal;
}
else if ((g.flags & 0x80) != 0)
{
g.color_table = g.pal;
}
else
{
return (byte*)(ulong)(stbi__err("missing color table") != 0 ? 0 : 0);
}
o = stbi__process_gif_raster(s, g);
if (o == null)
{
return null;
}
pcount = g.w * g.h;
if (first_frame != 0 && g.bgindex > 0)
{
for (pi = 0; pi < pcount; ++pi)
{
if (g.history[pi] == 0)
{
g.pal[g.bgindex][3] = 255;
fixed (byte* ptr = &g.pal[g.bgindex][0])
{
CRuntime.memcpy(&g._out_[pi * 4], ptr, (ulong)4);
}
}
}
}
return o;
}
case 0x21:
{
var len = 0;
int ext = stbi__get8(s);
if (ext == 0xF9)
{
len = stbi__get8(s);
if (len == 4)
{
g.eflags = stbi__get8(s);
g.delay = 10 * stbi__get16le(s);
if (g.transparent >= 0)
{
g.pal[g.transparent][3] = 255;
}
if ((g.eflags & 0x01) != 0)
{
g.transparent = stbi__get8(s);
if (g.transparent >= 0)
{
g.pal[g.transparent][3] = 0;
}
}
else
{
stbi__skip(s, 1);
g.transparent = -1;
}
}
else
{
stbi__skip(s, len);
break;
}
}
while ((len = stbi__get8(s)) != 0)
{
stbi__skip(s, len);
}
break;
}
case 0x3B:
return null;
default:
return (byte*)(ulong)(stbi__err("unknown code") != 0 ? 0 : 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 class stbi__gif
{
public byte* _out_;
public byte* background;
public int bgindex;
public stbi__gif_lzw[] codes = new stbi__gif_lzw[8192];
public byte[][] color_table;
public int cur_x;
public int cur_y;
public int delay;
public int eflags;
public int flags;
public int h;
public byte* history;
public int lflags;
public int line_size;
public byte[][] lpal = Utility.CreateArray<byte>(256, 4);
public int max_x;
public int max_y;
public byte[][] pal = Utility.CreateArray<byte>(256, 4);
public int parse;
public int ratio;
public int start_x;
public int start_y;
public int step;
public int transparent;
public int w;
}
[StructLayout(LayoutKind.Sequential)]
public struct stbi__gif_lzw
{
public short prefix;
public byte first;
public byte suffix;
}
}
}