XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
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;
    }
}