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
This commit is contained in:
@@ -34,13 +34,22 @@ namespace Misaki.HighPerformance.Image
|
||||
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);
|
||||
if (s.img_y > 1 << 24)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("too large") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
if (s.img_x > 1 << 24)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("too large") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
mr = info.mr;
|
||||
mg = info.mg;
|
||||
mb = info.mb;
|
||||
@@ -49,12 +58,16 @@ namespace Misaki.HighPerformance.Image
|
||||
if (info.hsz == 12)
|
||||
{
|
||||
if (info.bpp < 24)
|
||||
{
|
||||
psize = (info.offset - info.extra_read - 24) / 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.bpp < 16)
|
||||
{
|
||||
psize = (info.offset - info.extra_read - info.hsz) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (psize == 0)
|
||||
@@ -63,26 +76,47 @@ namespace Misaki.HighPerformance.Image
|
||||
var header_limit = 1024;
|
||||
var extra_data_limit = 256 * 4;
|
||||
if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("bad header") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("bad offset") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
stbi__skip(s, info.offset - bytes_read_so_far);
|
||||
}
|
||||
|
||||
if (info.bpp == 24 && ma == 0xff000000)
|
||||
{
|
||||
s.img_n = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 ? 0 : 0);
|
||||
}
|
||||
|
||||
_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 ? 0 : 0);
|
||||
}
|
||||
|
||||
if (info.bpp < 16)
|
||||
{
|
||||
var z = 0;
|
||||
@@ -98,7 +132,10 @@ namespace Misaki.HighPerformance.Image
|
||||
pal[i][1] = stbi__get8(s);
|
||||
pal[i][0] = stbi__get8(s);
|
||||
if (info.hsz != 12)
|
||||
{
|
||||
stbi__get8(s);
|
||||
}
|
||||
|
||||
pal[i][3] = 255;
|
||||
}
|
||||
|
||||
@@ -123,6 +160,7 @@ namespace Misaki.HighPerformance.Image
|
||||
|
||||
pad = -width & 3;
|
||||
if (info.bpp == 1)
|
||||
{
|
||||
for (j = 0; j < (int)s.img_y; ++j)
|
||||
{
|
||||
var bit_offset = 7;
|
||||
@@ -134,9 +172,15 @@ namespace Misaki.HighPerformance.Image
|
||||
_out_[z++] = pal[color][1];
|
||||
_out_[z++] = pal[color][2];
|
||||
if (target == 4)
|
||||
{
|
||||
_out_[z++] = 255;
|
||||
}
|
||||
|
||||
if (i + 1 == (int)s.img_x)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (--bit_offset < 0)
|
||||
{
|
||||
bit_offset = 7;
|
||||
@@ -146,7 +190,9 @@ namespace Misaki.HighPerformance.Image
|
||||
|
||||
stbi__skip(s, pad);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < (int)s.img_y; ++j)
|
||||
{
|
||||
for (i = 0; i < (int)s.img_x; i += 2)
|
||||
@@ -163,19 +209,28 @@ namespace Misaki.HighPerformance.Image
|
||||
_out_[z++] = pal[v][1];
|
||||
_out_[z++] = pal[v][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][0];
|
||||
_out_[z++] = pal[v][1];
|
||||
_out_[z++] = pal[v][2];
|
||||
if (target == 4)
|
||||
{
|
||||
_out_[z++] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
stbi__skip(s, pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -191,17 +246,30 @@ namespace Misaki.HighPerformance.Image
|
||||
var easy = 0;
|
||||
stbi__skip(s, info.offset - info.extra_read - 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)
|
||||
{
|
||||
@@ -240,7 +308,9 @@ namespace Misaki.HighPerformance.Image
|
||||
a = (byte)(easy == 2 ? stbi__get8(s) : 255);
|
||||
all_a |= a;
|
||||
if (target == 4)
|
||||
{
|
||||
_out_[z++] = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -256,7 +326,9 @@ namespace Misaki.HighPerformance.Image
|
||||
a = (uint)(ma != 0 ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
|
||||
all_a |= a;
|
||||
if (target == 4)
|
||||
{
|
||||
_out_[z++] = (byte)(a & 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,8 +337,12 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -288,13 +364,18 @@ namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
_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_;
|
||||
}
|
||||
|
||||
@@ -311,15 +392,25 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
if (x != null)
|
||||
{
|
||||
*x = (int)s.img_x;
|
||||
}
|
||||
|
||||
if (y != null)
|
||||
{
|
||||
*y = (int)s.img_y;
|
||||
}
|
||||
|
||||
if (comp != null)
|
||||
{
|
||||
if (info.bpp == 24 && info.ma == 0xff000000)
|
||||
{
|
||||
*comp = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*comp = info.ma != 0 ? 4 : 3;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -330,9 +421,15 @@ namespace Misaki.HighPerformance.Image
|
||||
var r = 0;
|
||||
var sz = 0;
|
||||
if (stbi__get8(s) != 66)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != 77)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
stbi__get32le(s);
|
||||
stbi__get16le(s);
|
||||
stbi__get16le(s);
|
||||
@@ -345,7 +442,10 @@ namespace Misaki.HighPerformance.Image
|
||||
public static int stbi__bmp_set_mask_defaults(stbi__bmp_data* info, int compress)
|
||||
{
|
||||
if (compress == 3)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (compress == 0)
|
||||
{
|
||||
if (info->bpp == 16)
|
||||
@@ -377,7 +477,10 @@ namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
var hsz = 0;
|
||||
if (stbi__get8(s) != 66 || stbi__get8(s) != 77)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("not BMP") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
stbi__get32le(s);
|
||||
stbi__get16le(s);
|
||||
stbi__get16le(s);
|
||||
@@ -386,9 +489,15 @@ namespace Misaki.HighPerformance.Image
|
||||
info->mr = info->mg = info->mb = info->ma = 0;
|
||||
info->extra_read = 14;
|
||||
if (info->offset < 0)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("unknown BMP") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
if (hsz == 12)
|
||||
{
|
||||
s.img_x = (uint)stbi__get16le(s);
|
||||
@@ -401,17 +510,29 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
if (stbi__get16le(s) != 1)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
info->bpp = stbi__get16le(s);
|
||||
if (hsz != 12)
|
||||
{
|
||||
var compress = (int)stbi__get32le(s);
|
||||
if (compress == 1 || compress == 2)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("BMP RLE") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
if (compress >= 4)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("BMP JPEG/PNG") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
if (compress == 3 && info->bpp != 16 && info->bpp != 32)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
stbi__get32le(s);
|
||||
stbi__get32le(s);
|
||||
stbi__get32le(s);
|
||||
@@ -440,7 +561,9 @@ namespace Misaki.HighPerformance.Image
|
||||
info->mb = stbi__get32le(s);
|
||||
info->extra_read += 12;
|
||||
if (info->mr == info->mg && info->mg == info->mb)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -452,16 +575,24 @@ namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
var i = 0;
|
||||
if (hsz != 108 && hsz != 124)
|
||||
{
|
||||
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
|
||||
}
|
||||
|
||||
info->mr = stbi__get32le(s);
|
||||
info->mg = stbi__get32le(s);
|
||||
info->mb = stbi__get32le(s);
|
||||
info->ma = stbi__get32le(s);
|
||||
if (compress != 3)
|
||||
{
|
||||
stbi__bmp_set_mask_defaults(info, compress);
|
||||
}
|
||||
|
||||
stbi__get32le(s);
|
||||
for (i = 0; i < 12; ++i)
|
||||
{
|
||||
stbi__get32le(s);
|
||||
}
|
||||
|
||||
if (hsz == 124)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user