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:
@@ -15,7 +15,7 @@ namespace Misaki.HighPerformance.Image
|
||||
public const int STBI__F_avg_first = 5;
|
||||
|
||||
public static byte[] first_row_filter =
|
||||
{ STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, STBI__F_sub };
|
||||
[STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, STBI__F_sub];
|
||||
|
||||
public static byte[] stbi__check_png_header_png_sig = { 137, 80, 78, 71, 13, 10, 26, 10 };
|
||||
public static byte[] stbi__depth_scale_table = { 0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01 };
|
||||
@@ -48,7 +48,9 @@ namespace Misaki.HighPerformance.Image
|
||||
var p = new stbi__png();
|
||||
p.s = s;
|
||||
if (stbi__png_info_raw(p, null, null, null) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (p.depth != 16)
|
||||
{
|
||||
stbi__rewind(p.s);
|
||||
@@ -70,8 +72,12 @@ namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
var i = 0;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (stbi__get8(s) != stbi__check_png_header_png_sig[i])
|
||||
{
|
||||
return stbi__err("bad png sig");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -90,12 +96,15 @@ namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
var i = 0;
|
||||
if (img_n == 1)
|
||||
{
|
||||
for (i = (int)(x - 1); i >= 0; --i)
|
||||
{
|
||||
dest[i * 2 + 1] = 255;
|
||||
dest[i * 2 + 0] = src[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = (int)(x - 1); i >= 0; --i)
|
||||
{
|
||||
dest[i * 4 + 3] = 255;
|
||||
@@ -103,6 +112,7 @@ namespace Misaki.HighPerformance.Image
|
||||
dest[i * 4 + 1] = src[i * 3 + 1];
|
||||
dest[i * 4 + 0] = src[i * 3 + 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,20 +133,36 @@ namespace Misaki.HighPerformance.Image
|
||||
var output_bytes = out_n * bytes;
|
||||
var filter_bytes = img_n * bytes;
|
||||
var width = (int)x;
|
||||
|
||||
a._out_ = (byte*)stbi__malloc_mad3((int)x, (int)y, output_bytes, 0);
|
||||
if (a._out_ == null)
|
||||
{
|
||||
return stbi__err("outofmem");
|
||||
}
|
||||
|
||||
if (stbi__mad3sizes_valid(img_n, (int)x, depth, 7) == 0)
|
||||
{
|
||||
return stbi__err("too large");
|
||||
}
|
||||
|
||||
img_width_bytes = (uint)((img_n * x * depth + 7) >> 3);
|
||||
if (stbi__mad2sizes_valid((int)img_width_bytes, (int)y, (int)img_width_bytes) == 0)
|
||||
{
|
||||
return stbi__err("too large");
|
||||
}
|
||||
|
||||
img_len = (img_width_bytes + 1) * y;
|
||||
if (raw_len < img_len)
|
||||
{
|
||||
return stbi__err("not enough pixels");
|
||||
}
|
||||
|
||||
filter_buf = (byte*)stbi__malloc_mad2((int)img_width_bytes, 2, 0);
|
||||
if (filter_buf == null)
|
||||
{
|
||||
return stbi__err("outofmem");
|
||||
}
|
||||
|
||||
if (depth < 8)
|
||||
{
|
||||
filter_bytes = 1;
|
||||
@@ -157,7 +183,10 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
filter = first_row_filter[filter];
|
||||
}
|
||||
|
||||
switch (filter)
|
||||
{
|
||||
case STBI__F_none:
|
||||
@@ -166,35 +195,49 @@ namespace Misaki.HighPerformance.Image
|
||||
case STBI__F_sub:
|
||||
CRuntime.memcpy(cur, raw, (ulong)filter_bytes);
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
{
|
||||
cur[k] = (byte)((raw[k] + cur[k - filter_bytes]) & 255);
|
||||
}
|
||||
|
||||
break;
|
||||
case STBI__F_up:
|
||||
for (k = 0; k < nk; ++k)
|
||||
{
|
||||
cur[k] = (byte)((raw[k] + prior[k]) & 255);
|
||||
}
|
||||
|
||||
break;
|
||||
case STBI__F_avg:
|
||||
for (k = 0; k < filter_bytes; ++k)
|
||||
{
|
||||
cur[k] = (byte)((raw[k] + (prior[k] >> 1)) & 255);
|
||||
}
|
||||
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
{
|
||||
cur[k] = (byte)((raw[k] + ((prior[k] + cur[k - filter_bytes]) >> 1)) & 255);
|
||||
}
|
||||
|
||||
break;
|
||||
case STBI__F_paeth:
|
||||
for (k = 0; k < filter_bytes; ++k)
|
||||
{
|
||||
cur[k] = (byte)((raw[k] + prior[k]) & 255);
|
||||
}
|
||||
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
{
|
||||
cur[k] = (byte)((raw[k] + stbi__paeth(cur[k - filter_bytes], prior[k],
|
||||
prior[k - filter_bytes])) & 255);
|
||||
}
|
||||
|
||||
break;
|
||||
case STBI__F_avg_first:
|
||||
CRuntime.memcpy(cur, raw, (ulong)filter_bytes);
|
||||
for (k = filter_bytes; k < nk; ++k)
|
||||
{
|
||||
cur[k] = (byte)((raw[k] + (cur[k - filter_bytes] >> 1)) & 255);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -208,39 +251,60 @@ namespace Misaki.HighPerformance.Image
|
||||
byte inb = 0;
|
||||
var nsmp = (uint)(x * img_n);
|
||||
if (depth == 4)
|
||||
{
|
||||
for (i = 0; i < nsmp; ++i)
|
||||
{
|
||||
if ((i & 1) == 0)
|
||||
{
|
||||
inb = *_in_++;
|
||||
}
|
||||
|
||||
*_out_++ = (byte)(scale * (inb >> 4));
|
||||
inb <<= 4;
|
||||
}
|
||||
}
|
||||
else if (depth == 2)
|
||||
{
|
||||
for (i = 0; i < nsmp; ++i)
|
||||
{
|
||||
if ((i & 3) == 0)
|
||||
{
|
||||
inb = *_in_++;
|
||||
}
|
||||
|
||||
*_out_++ = (byte)(scale * (inb >> 6));
|
||||
inb <<= 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < nsmp; ++i)
|
||||
{
|
||||
if ((i & 7) == 0)
|
||||
{
|
||||
inb = *_in_++;
|
||||
}
|
||||
|
||||
*_out_++ = (byte)(scale * (inb >> 7));
|
||||
inb <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (img_n != out_n)
|
||||
{
|
||||
stbi__create_png_alpha_expand8(dest, dest, x, img_n);
|
||||
}
|
||||
}
|
||||
else if (depth == 8)
|
||||
{
|
||||
if (img_n == out_n)
|
||||
{
|
||||
CRuntime.memcpy(dest, cur, (ulong)(x * img_n));
|
||||
}
|
||||
else
|
||||
{
|
||||
stbi__create_png_alpha_expand8(dest, cur, x, img_n);
|
||||
}
|
||||
}
|
||||
else if (depth == 16)
|
||||
{
|
||||
@@ -249,17 +313,22 @@ namespace Misaki.HighPerformance.Image
|
||||
if (img_n == out_n)
|
||||
{
|
||||
for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
|
||||
{
|
||||
*dest16 = (ushort)((cur[0] << 8) | cur[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (img_n == 1)
|
||||
{
|
||||
for (i = 0; i < x; ++i, dest16 += 2, cur += 2)
|
||||
{
|
||||
dest16[0] = (ushort)((cur[0] << 8) | cur[1]);
|
||||
dest16[1] = 0xffff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < x; ++i, dest16 += 4, cur += 6)
|
||||
{
|
||||
dest16[0] = (ushort)((cur[0] << 8) | cur[1]);
|
||||
@@ -267,13 +336,17 @@ namespace Misaki.HighPerformance.Image
|
||||
dest16[2] = (ushort)((cur[4] << 8) | cur[5]);
|
||||
dest16[3] = 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRuntime.free(filter_buf);
|
||||
if (all_ok == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -285,17 +358,23 @@ namespace Misaki.HighPerformance.Image
|
||||
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);
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
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;
|
||||
@@ -313,6 +392,7 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
for (j = 0; j < y; ++j)
|
||||
{
|
||||
for (i = 0; i < x; ++i)
|
||||
{
|
||||
var out_y = j * yspc[p] + yorig[p];
|
||||
@@ -320,6 +400,7 @@ namespace Misaki.HighPerformance.Image
|
||||
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;
|
||||
@@ -338,18 +419,25 @@ namespace Misaki.HighPerformance.Image
|
||||
var pixel_count = s.img_x * s.img_y;
|
||||
var p = z._out_;
|
||||
if (out_n == 2)
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
p[1] = (byte)(p[0] == tc[0] ? 0 : 255);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
|
||||
{
|
||||
p[3] = 0;
|
||||
}
|
||||
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -361,18 +449,25 @@ namespace Misaki.HighPerformance.Image
|
||||
var pixel_count = s.img_x * s.img_y;
|
||||
var p = (ushort*)z._out_;
|
||||
if (out_n == 2)
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
p[1] = (ushort)(p[0] == tc[0] ? 0 : 65535);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
|
||||
{
|
||||
p[3] = 0;
|
||||
}
|
||||
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -386,9 +481,12 @@ namespace Misaki.HighPerformance.Image
|
||||
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 = 0; i < pixel_count; ++i)
|
||||
{
|
||||
var n = orig[i] * 4;
|
||||
@@ -397,7 +495,9 @@ namespace Misaki.HighPerformance.Image
|
||||
p[2] = palette[n + 2];
|
||||
p += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
var n = orig[i] * 4;
|
||||
@@ -407,6 +507,7 @@ namespace Misaki.HighPerformance.Image
|
||||
p[3] = palette[n + 3];
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
|
||||
CRuntime.free(a._out_);
|
||||
a._out_ = temp_out;
|
||||
@@ -423,9 +524,7 @@ namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
var t = p[0];
|
||||
p[0] = p[2];
|
||||
p[2] = t;
|
||||
(p[2], p[0]) = (p[0], p[2]);
|
||||
p += 3;
|
||||
}
|
||||
}
|
||||
@@ -434,6 +533,7 @@ namespace Misaki.HighPerformance.Image
|
||||
if ((stbi__unpremultiply_on_load_set != 0
|
||||
? stbi__unpremultiply_on_load_local
|
||||
: stbi__unpremultiply_on_load_global) != 0)
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
var a = p[3];
|
||||
@@ -453,14 +553,15 @@ namespace Misaki.HighPerformance.Image
|
||||
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < pixel_count; ++i)
|
||||
{
|
||||
var t = p[0];
|
||||
p[0] = p[2];
|
||||
p[2] = t;
|
||||
(p[2], p[0]) = (p[0], p[2]);
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,10 +585,17 @@ namespace Misaki.HighPerformance.Image
|
||||
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);
|
||||
@@ -502,50 +610,92 @@ namespace Misaki.HighPerformance.Image
|
||||
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);
|
||||
s.img_y = stbi__get32be(s);
|
||||
if (s.img_y > 1 << 24)
|
||||
{
|
||||
return stbi__err("too large");
|
||||
}
|
||||
|
||||
if (s.img_x > 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");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s.img_n = 1;
|
||||
if ((1 << 30) / s.img_x / 4 < s.img_y)
|
||||
{
|
||||
return stbi__err("too large");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -554,12 +704,21 @@ namespace Misaki.HighPerformance.Image
|
||||
case ((uint)80 << 24) + ((uint)76 << 16) + ((uint)84 << 8) + 69:
|
||||
{
|
||||
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 = 0; i < pal_len; ++i)
|
||||
{
|
||||
palette[i * 4 + 0] = stbi__get8(s);
|
||||
@@ -574,9 +733,15 @@ namespace Misaki.HighPerformance.Image
|
||||
case ((uint)116 << 24) + ((uint)82 << 16) + ((uint)78 << 8) + 83:
|
||||
{
|
||||
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)
|
||||
@@ -586,19 +751,33 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
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 = 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 (scan == STBI__SCAN_header)
|
||||
{
|
||||
@@ -607,11 +786,19 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
if (z.depth == 16)
|
||||
{
|
||||
for (k = 0; k < s.img_n && k < 3; ++k)
|
||||
{
|
||||
tc16[k] = (ushort)stbi__get16be(s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (k = 0; k < s.img_n && k < 3; ++k)
|
||||
{
|
||||
tc[k] = (byte)((byte)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z.depth]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -620,37 +807,63 @@ namespace Misaki.HighPerformance.Image
|
||||
case ((uint)73 << 24) + ((uint)68 << 16) + ((uint)65 << 8) + 84:
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (pal_img_n != 0)
|
||||
{
|
||||
s.img_n = pal_img_n;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (c.length > 1u << 30)
|
||||
{
|
||||
return stbi__err("IDAT size limit");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -660,36 +873,60 @@ namespace Misaki.HighPerformance.Image
|
||||
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 ? 1 : 0);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,15 +934,23 @@ namespace Misaki.HighPerformance.Image
|
||||
(stbi__de_iphone_flag_set != 0
|
||||
? stbi__de_iphone_flag_local
|
||||
: stbi__de_iphone_flag_global) != 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)
|
||||
{
|
||||
@@ -720,7 +965,10 @@ namespace Misaki.HighPerformance.Image
|
||||
|
||||
default:
|
||||
if (first != 0)
|
||||
{
|
||||
return stbi__err("first not IHDR");
|
||||
}
|
||||
|
||||
if ((c.type & (1 << 29)) == 0)
|
||||
{
|
||||
stbi__parse_png_file_invalid_chunk[0] = (char)((c.type >> 24) & 255);
|
||||
@@ -742,32 +990,51 @@ namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
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_);
|
||||
@@ -788,11 +1055,20 @@ namespace Misaki.HighPerformance.Image
|
||||
}
|
||||
|
||||
if (x != null)
|
||||
{
|
||||
*x = (int)p.s.img_x;
|
||||
}
|
||||
|
||||
if (y != null)
|
||||
{
|
||||
*y = (int)p.s.img_y;
|
||||
}
|
||||
|
||||
if (comp != null)
|
||||
{
|
||||
*comp = p.s.img_n;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user