Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Resize (thay đổi kích thước) Image trong C#

Sử dụng System.Drawing.Common (Windows) hoặc ImageSharp (cross-platform) để resize ảnh.

Cách 1: System.Drawing.Common (Chỉ Windows / Linux với libgdiplus)

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

public static void ResizeImage(string inputPath, string outputPath, int maxWidth, int maxHeight, long quality = 85L)
{
    using var original = Image.FromFile(inputPath);
    
    // Tính kích thước mới giữ aspect ratio
    var newSize = CalculateNewSize(original.Width, original.Height, maxWidth, maxHeight);
    
    using var resized = new Bitmap(newSize.Width, newSize.Height);
    using var graphics = Graphics.FromImage(resized);
    
    // Chất lượng cao
    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
    graphics.CompositingQuality = CompositingQuality.HighQuality;
    graphics.SmoothingMode = SmoothingMode.HighQuality;
    graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
    
    graphics.DrawImage(original, 0, 0, newSize.Width, newSize.Height);
    
    // Encoder parameters cho JPEG quality
    var encoderParams = new EncoderParameters(1);
    encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
    
    var jpegCodec = GetEncoderInfo("image/jpeg");
    resized.Save(outputPath, jpegCodec, encoderParams);
}

static Size CalculateNewSize(int origW, int origH, int maxW, int maxH)
{
    double ratio = Math.Min((double)maxW / origW, (double)maxH / origH);
    return new Size((int)(origW * ratio), (int)(origH * ratio));
}

static ImageCodecInfo GetEncoderInfo(string mimeType)
{
    return ImageCodecInfo.GetImageEncoders().FirstOrDefault(c => c.MimeType == mimeType);
}

Cách 2: ImageSharp (Cross-platform, khuyến nghị cho .NET Core/5+)

// NuGet: SixLabors.ImageSharp
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Jpeg;

public static void ResizeImageSharp(string inputPath, string outputPath, int maxWidth, int maxHeight, int quality = 85)
{
    using var image = Image.Load(inputPath);
    
    image.Mutate(x => x.Resize(new ResizeOptions
    {
        Mode = ResizeMode.Max, // Giữ aspect ratio, fit trong maxWidth x maxHeight
        Size = new Size(maxWidth, maxHeight)
    }));
    
    image.Save(outputPath, new JpegEncoder { Quality = quality });
}

Cách 3: SkiaSharp (Cross-platform, hiệu năng cao)

// NuGet: SkiaSharp
using SkiaSharp;

public static void ResizeSkia(string inputPath, string outputPath, int maxWidth, int maxHeight, int quality = 85)
{
    using var inputStream = File.OpenRead(inputPath);
    using var original = SKBitmap.Decode(inputStream);
    
    var newSize = CalculateNewSize(original.Width, original.Height, maxWidth, maxHeight);
    using var resized = original.Resize(new SKImageInfo(newSize.Width, newSize.Height), SKFilterQuality.High);
    
    using var image = SKImage.FromBitmap(resized);
    using var data = image.Encode(SKEncodedImageFormat.Jpeg, quality);
    using var outputStream = File.OpenWrite(outputPath);
    data.SaveTo(outputStream);
}

So sánh thư viện

Thư việnPlatformHiệu năngTính năngKhuyến nghị
System.Drawing.CommonWindows (Linux cần libgdiplus)Trung bìnhCơ bảnLegacy WinForms/WPF
ImageSharpCross-platform (managed 100%)TốtĐầy đủ, fluent API⭐ Mới, web, cloud
SkiaSharpCross-platform (native Skia)Rất tốtNâng cao, 2D graphicsHigh perf, mobile, game
Magick.NETCross-platform (ImageMagick)Rất tốtRất đầy đủ (100+ format)Complex processing

Lưu ý quan trọng

  • Dispose đúng cách: Image, Graphics, Bitmap, Stream đều implement IDisposable -> dùng using.
  • Aspect ratio: Luôn giữ tỷ lệ để không biến dạng ảnh.
  • Memory: Ảnh lớn -> load vào memory -> OOM. Dùng stream, decode bounds trước (SkiaSharp/ImageSharp hỗ trợ).
  • EXIF Orientation: Ảnh từ điện thoại có thể xoay. ImageSharp/SkiaSharp tự handle, System.Drawing cần code thêm.