using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace XFESystem.Browser;
internal static class BrowserImageDecoder
{
private static readonly DecoderOptions options = new()
{
Configuration = new Configuration(new JpegConfigurationModule(), new WebpConfigurationModule(), new GifConfigurationModule())
{
MaxDegreeOfParallelism = 1,
MemoryAllocator = MemoryAllocator.Create(new MemoryAllocatorOptions { AllocationLimitMegabytes = 128, MaximumPoolSizeMegabytes = 0 })
},
SkipMetadata = true, MaxFrames = 1
};
internal static BrowserCanvasSurface Decode(byte[] bytes, int maximumPixels)
{
if (BrowserPngDecoder.HasSignature(bytes)) return BrowserPngDecoder.Decode(bytes, maximumPixels);
if (System.Text.Encoding.UTF8.GetString(bytes.AsSpan(0, Math.Min(256, bytes.Length))).TrimStart('\uFEFF', ' ', '\r', '\n', '\t').StartsWith('<'))
return BrowserSvgRasterizer.Decode(bytes, maximumPixels);
using var stream = new MemoryStream(bytes, false);
var info = Image.Identify(options, stream);
if (info.Width <= 0 || info.Height <= 0 || (long)info.Width * info.Height > maximumPixels)
throw new BrowserLimitException("The image dimensions exceed the decoded pixel budget.");
stream.Position = 0;
using var image = Image.Load<Rgba32>(options, stream);
if (image.Width != info.Width || image.Height != info.Height)
throw new IOException("The decoded image dimensions differ from its header.");
var surface = new BrowserCanvasSurface(image.Width, image.Height);
image.ProcessPixelRows(accessor =>
{
for (int y = 0; y < accessor.Height; y++)
{
var row = accessor.GetRowSpan(y);
for (int x = 0; x < row.Length; x++)
{ var pixel = row[x]; surface.PutPixel(x, y, (uint)(pixel.A << 24 | pixel.R << 16 | pixel.G << 8 | pixel.B)); }
}
});
surface.Commit();
return surface;
}
}
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace XFESystem.Browser;
internal static class BrowserImageDecoder
{
private static readonly DecoderOptions options = new()
{
Configuration = new Configuration(new JpegConfigurationModule(), new WebpConfigurationModule(), new GifConfigurationModule())
{
MaxDegreeOfParallelism = 1,
MemoryAllocator = MemoryAllocator.Create(new MemoryAllocatorOptions { AllocationLimitMegabytes = 128, MaximumPoolSizeMegabytes = 0 })
},
SkipMetadata = true, MaxFrames = 1
};
internal static BrowserCanvasSurface Decode(byte[] bytes, int maximumPixels)
{
if (BrowserPngDecoder.HasSignature(bytes)) return BrowserPngDecoder.Decode(bytes, maximumPixels);
if (System.Text.Encoding.UTF8.GetString(bytes.AsSpan(0, Math.Min(256, bytes.Length))).TrimStart('\uFEFF', ' ', '\r', '\n', '\t').StartsWith('<'))
return BrowserSvgRasterizer.Decode(bytes, maximumPixels);
using var stream = new MemoryStream(bytes, false);
var info = Image.Identify(options, stream);
if (info.Width <= 0 || info.Height <= 0 || (long)info.Width * info.Height > maximumPixels)
throw new BrowserLimitException("The image dimensions exceed the decoded pixel budget.");
stream.Position = 0;
using var image = Image.Load<Rgba32>(options, stream);
if (image.Width != info.Width || image.Height != info.Height)
throw new IOException("The decoded image dimensions differ from its header.");
var surface = new BrowserCanvasSurface(image.Width, image.Height);
image.ProcessPixelRows(accessor =>
{
for (int y = 0; y < accessor.Height; y++)
{
var row = accessor.GetRowSpan(y);
for (int x = 0; x < row.Length; x++)
{ var pixel = row[x]; surface.PutPixel(x, y, (uint)(pixel.A << 24 | pixel.R << 16 | pixel.G << 8 | pixel.B)); }
}
});
surface.Commit();
return surface;
}
}