首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

.NET C# 縮圖生成核心邏輯深度拆解與擴充實作

     編輯:ASP.NET 基礎

核心演算法邏輯

縮圖生成的本質是幾何映射與像素重採樣。Graphics.DrawImage 透過「來源矩形 → 目標矩形」的仿射變換,配合插值演算法決定輸出品質。本文拆解關鍵計算步驟,並提供支援多種輸出格式的擴充實作。

四大縮放模式數學推導

設原圖寬高 (ow, oh),目標 (tw, th):

  • HW (強制):srcRect = (0,0,ow,oh) → destRect = (0,0,tw,th),直接拉伸。
  • W (寬度基準):th = oh * tw / ow,高度等比縮放。
  • H (高度基準):tw = ow * th / oh,寬度等比縮放。
  • Cut (置中裁切):
    
    double targetRatio = (double)tw / th;
    double sourceRatio = (double)ow / oh;
    if (sourceRatio > targetRatio) // 原圖較寬 → 左右裁切
    {
        srcH = oh;
        srcW = (int)(oh * targetRatio);
        x = (ow - srcW) / 2;
    }
    else // 原圖較高 → 上下裁切
    {
        srcW = ow;
        srcH = (int)(ow / targetRatio);
        y = (oh - srcH) / 2;
    }
        

高品質輸出關鍵設定


g.InterpolationMode = InterpolationMode.HighQualityBicubic; // 雙三次插值,縮放最佳
g.SmoothingMode = SmoothingMode.HighQuality;               // 邊緣平滑
g.PixelOffsetMode = PixelOffsetMode.HighQuality;           // 像素偏移修正
g.CompositingQuality = CompositingQuality.HighQuality;     // 合成品質

完整擴充實作:支援多格式輸出


public static class ThumbnailExtensions
{
    public enum Mode { HW, W, H, Cut }

    public static void Generate(
        string sourcePath, string destPath,
        int width, int height, Mode mode,
        ImageFormat format = null)
    {
        using (Image src = Image.FromFile(sourcePath))
        {
            int ow = src.Width, oh = src.Height;
            int tw = width, th = height;
            int sx = 0, sy = 0, sw = ow, sh = oh;

            switch (mode)
            {
                case Mode.W: th = oh * tw / ow; break;
                case Mode.H: tw = ow * th / oh; break;
                case Mode.Cut:
                    double tr = (double)tw / th, sr = (double)ow / oh;
                    if (sr > tr) { sh = oh; sw = (int)(oh * tr); sx = (ow - sw) / 2; }
                    else { sw = ow; sh = (int)(ow / tr); sy = (oh - sh) / 2; }
                    break;
            }

            using (Bitmap bmp = new Bitmap(tw, th))
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.Clear(Color.Transparent);
                g.DrawImage(src, new Rectangle(0, 0, tw, th), new Rectangle(sx, sy, sw, sh), GraphicsUnit.Pixel);

                // 預設 JPEG,支援自訂格式
                bmp.Save(destPath, format ?? ImageFormat.Jpeg);
            }
        }
    }
}

// 呼叫範例
ThumbnailExtensions.Generate("src.jpg", "thumb.png", 200, 200, ThumbnailExtensions.Mode.Cut, ImageFormat.Png);

常見坑點與解決方案

問題原因解決
縮圖背景變黑PNG 透明背景未處理g.Clear(Color.Transparent) + 確保目標 Bitmap 為 32bppArgb
GIF 動畫只取第一幀Image.FromFile 僅載入第一幀使用 ImageSharp 或 System.Drawing.Common 逐幀處理
大圖 OOM一次載入完整像素陣列分塊處理或改用 ImageSharp 串流解碼
Linux 部署失敗libgdiplus 缺失安裝 libgdiplus 或改用跨平台庫

效能優化建議

  • 快取原圖尺寸:避免重複 Image.FromFile 讀取檔案頭。
  • 非同步管線:Task.Run 卸載 CPU 密集運算,避免阻塞 UI/請求執行緒。
  • 物件池:高併發場景下重用 Bitmap/Graphics 減少 GC 壓力。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved