dramaling-vocab-learning/backend/DramaLing.Api/Services/ImageProcessingService.cs

86 lines
3.0 KiB
C#

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Png;
namespace DramaLing.Api.Services;
public class ImageProcessingService : IImageProcessingService
{
private readonly ILogger<ImageProcessingService> _logger;
public ImageProcessingService(ILogger<ImageProcessingService> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<byte[]> ResizeImageAsync(byte[] originalBytes, int targetWidth, int targetHeight)
{
try
{
_logger.LogInformation("Resizing image from {OriginalSize}KB to {TargetWidth}x{TargetHeight}",
originalBytes.Length / 1024, targetWidth, targetHeight);
using var image = Image.Load(originalBytes);
_logger.LogDebug("Original image size: {Width}x{Height}", image.Width, image.Height);
// 使用高品質的 Lanczos3 重採樣算法
image.Mutate(x => x.Resize(targetWidth, targetHeight, KnownResamplers.Lanczos3));
using var output = new MemoryStream();
// 使用 PNG 格式儲存,保持品質
await image.SaveAsPngAsync(output, new PngEncoder
{
CompressionLevel = PngCompressionLevel.Level6, // 平衡壓縮和品質
ColorType = PngColorType.Rgb
});
var resizedBytes = output.ToArray();
_logger.LogInformation("Image resized successfully. New size: {NewSize}KB (reduction: {Reduction:P})",
resizedBytes.Length / 1024,
1.0 - (double)resizedBytes.Length / originalBytes.Length);
return resizedBytes;
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to resize image");
throw;
}
}
public async Task<byte[]> OptimizeImageAsync(byte[] originalBytes, int quality = 85)
{
try
{
_logger.LogInformation("Optimizing image, original size: {OriginalSize}KB",
originalBytes.Length / 1024);
using var image = Image.Load(originalBytes);
using var output = new MemoryStream();
// 針對例句圖的優化設定
await image.SaveAsPngAsync(output, new PngEncoder
{
CompressionLevel = PngCompressionLevel.Level9, // 最高壓縮
ColorType = PngColorType.Rgb,
BitDepth = PngBitDepth.Bit8
});
var optimizedBytes = output.ToArray();
_logger.LogInformation("Image optimized successfully. New size: {NewSize}KB (reduction: {Reduction:P})",
optimizedBytes.Length / 1024,
1.0 - (double)optimizedBytes.Length / originalBytes.Length);
return optimizedBytes;
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to optimize image");
throw;
}
}
}