Lagrange.Core/Lagrange.Core/Utility/ImageResolver.cs

78 lines
3.2 KiB
C#

using System.Numerics;
using BitConverter = Lagrange.Core.Utility.Binary.BitConverter;
namespace Lagrange.Core.Utility;
internal static class ImageResolver
{
public static ImageFormat Resolve(byte[] image, out Vector2 size)
{
if (image[..6].SequenceEqual(new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }) ||
image[..6].SequenceEqual(new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 })) // GIF89a / GIF87a
{
size = new Vector2(BitConverter.ToUInt16(image.AsSpan()[6..8]), BitConverter.ToUInt16(image.AsSpan()[8..10]));
return ImageFormat.Gif;
}
if (image[..2].SequenceEqual(new byte[] { 0xFF, 0xD8 })) // JPEG
{
size = Vector2.Zero;
if (image[2..4].SequenceEqual(new byte[] { 0xFF, 0xE0 })) // JFIF
{
for (int i = 4; i < image.Length - 1; i++)
{
if (image[i] == 0xFF && image[i + 1] >= 0xC0 && image[i + 1] <= 0xC3) // SOF0 ~ SOF3
{
size = new Vector2(BitConverter.ToUInt16(image.AsSpan()[(i + 7)..(i + 9)], false),BitConverter.ToUInt16(image.AsSpan()[(i + 5)..(i + 7)], false));
break;
}
}
}
return ImageFormat.Jpeg;
}
if (image[..8].SequenceEqual(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A })) // PNG
{
size = new Vector2(BitConverter.ToUInt32(image.AsSpan()[16..20], false), BitConverter.ToUInt32(image.AsSpan()[20..24], false));
return ImageFormat.Png;
}
if (image[..4].SequenceEqual(new byte[] { 0x52, 0x49, 0x46, 0x46 }) && image[8..12].SequenceEqual(new byte[] { 0x57, 0x45, 0x42, 0x50 })) // RIFF WEBP
{
if (image[12..16].SequenceEqual(new byte[] { 0x56, 0x50, 0x38, 0x58 })) // VP8X
size = new Vector2(BitConverter.ToUInt16(image.AsSpan()[24..27]) + 1, BitConverter.ToUInt16(image.AsSpan()[27..30]) + 1);
else if (image[12..16].SequenceEqual(new byte[] { 0x56, 0x50, 0x38, 0x4C })) // VP8L
size = new Vector2((BitConverter.ToInt32(image.AsSpan()[21..25]) & 0x3FFF) + 1, ((BitConverter.ToInt32(image.AsSpan()[21..25]) & 0xFFFC000) >> 0x0E) + 1);
else // VP8
size = new Vector2(BitConverter.ToUInt16(image.AsSpan()[26..28]), BitConverter.ToUInt16(image.AsSpan()[28..30]));
return ImageFormat.Webp;
}
if (image[..2].SequenceEqual(new byte[] { 0x42, 0x4D })) // BMP
{
size = new Vector2(BitConverter.ToUInt16(image.AsSpan()[18..20]), BitConverter.ToUInt16(image.AsSpan()[22..24]));
return ImageFormat.Bmp;
}
if (image[..2].SequenceEqual(new byte[] { 0x49, 0x49 }) || image[..2].SequenceEqual(new byte[] { 0x4D, 0x4D })) // TIFF
{
size = new Vector2(BitConverter.ToUInt16(image.AsSpan()[18..20]), BitConverter.ToUInt16(image.AsSpan()[30..32]));
return ImageFormat.Tiff;
}
size = Vector2.Zero;
return ImageFormat.Unknown;
}
}
internal enum ImageFormat
{
Unknown,
Png,
Jpeg,
Gif,
Webp,
Bmp,
Tiff
}