Reworked image handling, added banner for profiles. Made functions to start on xivauth. Refactored some code.
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
|
||||
namespace LightlessSyncServer.Services
|
||||
{
|
||||
public class ImageCheckService
|
||||
{
|
||||
private static readonly int _imageWidthAvatar = 512;
|
||||
private static readonly int _imageHeightAvatar = 512;
|
||||
private static readonly int _imageWidthBanner = 840;
|
||||
private static readonly int _imageHeightBanner = 260;
|
||||
private static readonly int _imageSize = 2000;
|
||||
|
||||
public class ImageLoadResult
|
||||
{
|
||||
public bool Success { get; init; }
|
||||
public string? Base64Image { get; init; }
|
||||
public string? ErrorMessage { get; init; }
|
||||
|
||||
public static ImageLoadResult Fail(string message) => new()
|
||||
{
|
||||
Success = false,
|
||||
ErrorMessage = message,
|
||||
};
|
||||
|
||||
public static ImageLoadResult Ok(string base64) => new()
|
||||
{
|
||||
Success = true,
|
||||
Base64Image = base64,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static async Task<ImageLoadResult> ValidateImageAsync(string base64String, bool banner, CancellationToken token)
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
return ImageLoadResult.Fail("Operation cancelled.");
|
||||
|
||||
byte[] imageData;
|
||||
try
|
||||
{
|
||||
imageData = Convert.FromBase64String(base64String);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return ImageLoadResult.Fail("The provided image is not a valid Base64 string.");
|
||||
}
|
||||
|
||||
Image<Rgba32>? image = null;
|
||||
bool imageLoaded = false;
|
||||
IImageFormat? format = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var ms = new MemoryStream(imageData))
|
||||
{
|
||||
format = await Image.DetectFormatAsync(ms, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (format == null)
|
||||
{
|
||||
return ImageLoadResult.Fail("Unable to detect image format.");
|
||||
}
|
||||
|
||||
using (image = Image.Load<Rgba32>(imageData))
|
||||
{
|
||||
imageLoaded = true;
|
||||
|
||||
int maxWidth = banner ? _imageWidthBanner : _imageWidthAvatar;
|
||||
int maxHeight = banner ? _imageHeightBanner : _imageHeightAvatar;
|
||||
|
||||
if (image.Width > maxWidth || image.Height > maxHeight)
|
||||
{
|
||||
var ratio = Math.Min((double)maxWidth / image.Width, (double)maxHeight / image.Height);
|
||||
int newWidth = (int)(image.Width * ratio);
|
||||
int newHeight = (int)(image.Height * ratio);
|
||||
|
||||
image.Mutate(x => x.Resize(newWidth, newHeight));
|
||||
}
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
|
||||
await image.SaveAsPngAsync(memoryStream, token).ConfigureAwait(false);
|
||||
|
||||
if (memoryStream.Length > _imageSize * 1024)
|
||||
{
|
||||
return ImageLoadResult.Fail("Your image exceeds 2 MiB after resizing/conversion.");
|
||||
}
|
||||
|
||||
string base64Png = Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
|
||||
return ImageLoadResult.Ok(base64Png);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (imageLoaded)
|
||||
image?.Dispose();
|
||||
|
||||
return ImageLoadResult.Fail("Failed to load or process the image. It may be corrupted or unsupported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user