using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenArchival.Blazor.CustomComponents; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using System.IO; namespace OpenArchival.DataAccess.FileAccessManager; public class ImageThumbnailer : IImageThumbnailer { private readonly IOptions _fileUploadOptions; private readonly ILogger _logger; private static readonly string[] SupportedExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tiff" }; public ImageThumbnailer(IOptions fileUploadOptions, ILogger logger) { _fileUploadOptions = fileUploadOptions; _logger = logger; } public async Task GenerateThumbnailsAsync(string originalFilePath) { if (!File.Exists(originalFilePath)) { _logger.LogError("Original file not found: {Path}", originalFilePath); throw new FileNotFoundException("Original file not found", originalFilePath); } if (!IsSupportedImage(originalFilePath)) { _logger.LogWarning("File is not a supported image format: {Path}", originalFilePath); return new ThumbnailResult(string.Empty, string.Empty); } var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFilePath); var thumbnailFolder = _fileUploadOptions.Value.ThumbnailFolderPath; if (!Directory.Exists(thumbnailFolder)) { Directory.CreateDirectory(thumbnailFolder); } var smallPath = Path.Combine(thumbnailFolder, $"{fileNameWithoutExtension}_small.webp"); var largePath = Path.Combine(thumbnailFolder, $"{fileNameWithoutExtension}_large.webp"); using (var image = await Image.LoadAsync(originalFilePath)) { await Task.WhenAll( CreateThumbnailAsync(image.Clone(x => { }), smallPath, _fileUploadOptions.Value.SmallThumbnailSize), CreateThumbnailAsync(image.Clone(x => { }), largePath, _fileUploadOptions.Value.LargeThumbnailSize) ); } return new ThumbnailResult(smallPath, largePath); } public bool IsSupportedImage(string filePath) { var extension = Path.GetExtension(filePath).ToLowerInvariant(); return SupportedExtensions.Contains(extension); } private async Task CreateThumbnailAsync(Image image, string outputPath, int maxSize) { using (image) { int width, height; if (image.Width > image.Height) { width = maxSize; height = (int)((double)image.Height / image.Width * maxSize); } else { height = maxSize; width = (int)((double)image.Width / image.Height * maxSize); } image.Mutate(x => x.Resize(new ResizeOptions { Size = new Size(width, height), Mode = ResizeMode.Max })); await image.SaveAsWebpAsync(outputPath); } } }