Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

วิธี Resize/Compress รูปภาพ (Image) ใน C#

ใช้ Namespace System.Drawing (Windows Forms) หรือ System.Drawing.Common (Cross-platform) และ System.Drawing.Imaging สำหรับ Encoder/Quality

ตัวอย่าง: Compress และ Save JPEG ด้วย Quality Setting

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using System.Security.Principal;

public class ImageHelper
{
    public async Task<string> CompressAndSaveImageAsync(Bitmap inputImage, int quality = 50)
    {
        string imageSavedPath = string.Empty;
        
        try
        {
            // 1. หา JPEG Encoder
            ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
            
            // 2. ตั้งค่า Quality (0-100)
            Encoder qualityEncoder = Encoder.Quality;
            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(qualityEncoder, quality);
            
            // 3. สร้างชื่อไฟล์ Unique (User + Timestamp)
            string userId = Regex.Replace(WindowsIdentity.GetCurrent().Name, @"[^0-9a-zA-Z]+", "_");
            string timestamp = Regex.Replace(DateTimeOffset.Now.ToString("yyyyMMddHHmmss"), @"[^0-9]", "");
            string fileName = $"{userId}_{timestamp}.jpg";
            
            // 4. Save Path
            string saveFolder = @"C:\Images\Compressed";
            Directory.CreateDirectory(saveFolder);
            imageSavedPath = Path.Combine(saveFolder, fileName);
            
            // 5. Save และ Dispose
            inputImage.Save(imageSavedPath, jpgEncoder, encoderParams);
            inputImage.Dispose();
        }
        catch (Exception ex)
        {
            // Log Error
            throw;
        }
        
        return imageSavedPath;
    }
    
    private ImageCodecInfo GetEncoder(ImageFormat format)
    {
        foreach (var codec in ImageCodecInfo.GetImageEncoders())
        {
            if (codec.FormatID == format.Guid)
                return codec;
        }
        return null;
    }
}

ตัวอย่าง: Resize Image (ปรับขนาด Pixel)

public static Bitmap ResizeImage(Image source, int maxWidth, int maxHeight)
{
    // คำนวณ Ratio รักษาสัดส่วน
    double ratioX = (double)maxWidth / source.Width;
    double ratioY = (double)maxHeight / source.Height;
    double ratio = Math.Min(ratioX, ratioY);
    
    int newWidth = (int)(source.Width * ratio);
    int newHeight = (int)(source.Height * ratio);
    
    // สร้าง Bitmap ใหม่
    var dest = new Bitmap(newWidth, newHeight);
    
    using (var graphics = Graphics.FromImage(dest))
    {
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.DrawImage(source, 0, 0, newWidth, newHeight);
    }
    
    return dest;
}

// ใช้งานร่วมกับ Compress
public async Task<string> ResizeAndCompressAsync(string sourcePath, int maxWidth, int maxHeight, int quality = 80)
{
    using var original = Image.FromFile(sourcePath);
    using var resized = ResizeImage(original, maxWidth, maxHeight);
    return await CompressAndSaveImageAsync((Bitmap)resized, quality);
}

การใช้งาน

static async Task Main()
{
    var helper = new ImageHelper();
    
    // โหลดรูปต้นฉบับ
    using var original = new Bitmap(@"C:\Photos\original.jpg");
    
    // Resize + Compress
    string savedPath = await helper.ResizeAndCompressAsync(
        @"C:\Photos\original.jpg", 
        maxWidth: 1920, 
        maxHeight: 1080, 
        quality: 85);
    
    Console.WriteLine($"Saved to: {savedPath}");
}

ข้อควรระวัง

  • System.Drawing.Common ใน Linux/Mac ต้องติดตั้ง libgdiplus
  • Memory: Bitmap ใช้ Unmanaged Memory → ต้อง Dispose() เสมอ (ใช้ using)
  • Quality: 75-90 สำหรับ Web, 90-100 สำหรับ Print
  • Format: JPEG สำหรับ Photo, PNG สำหรับ Graphics/Text (Lossless)
  • EXIF Orientation: รูปจากมือถืออาจหมุน → ต้องอ่าน EXIF และ Rotate ก่อน Resize

Alternative Libraries (Modern, Cross-platform)

  • ImageSharp (SixLabors.ImageSharp) - Pure C#, No Native Dependencies ⭐ Recommended
  • SkiaSharp - Google Skia, High Performance
  • Magick.NET - ImageMagick Wrapper, Powerful

ตัวอย่างด้วย ImageSharp (แนะนำสำหรับ .NET Core/5+)

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

public async Task ResizeAndSaveSharp(string inputPath, string outputPath, int width, int height, int quality = 80)
{
    using var image = await Image.LoadAsync(inputPath);
    image.Mutate(x => x.Resize(new ResizeOptions
    {
        Size = new Size(width, height),
        Mode = ResizeMode.Max, // Keep Aspect Ratio
        Sampler = KnownResamplers.Lanczos3
    }));
    
    await image.SaveAsync(outputPath, new JpegEncoder { Quality = quality });
}