86 lines
3.0 KiB
C#
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;
|
|
}
|
|
}
|
|
} |