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

ASP.NET 生成高品質縮略圖通用函數:四種模式、插值算法與資源釋放最佳實踐

     編輯:關於ASP.NET

功能需求

網站常需生成縮略圖。.NET `System.Drawing` 提供完整繪圖功能,封裝通用方法支援四種模式:

  1. HW:指定寬高強制縮放 (可能變形)。
  2. W:指定寬,高按原比例縮放。
  3. H:指定高,寬按原比例縮放。
  4. Cut:指定寬高裁切置中 (不變形,類似 CSS `object-fit: cover`)。

完整實作程式碼

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

public static class ImageHelper
{
    /// 
    /// 生成高品質縮略圖
    /// 
    /// 源圖實體路徑
    /// 縮略圖儲存實體路徑
    /// 目標寬度
    /// 目標高度
    /// 模式: HW(強制縮放) W(寬優先) H(高優先) Cut(裁切置中)
    public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, string mode)
    {
        using (Image originalImage = Image.FromFile(originalImagePath))
        {
            int toWidth = width;
            int toHeight = height;
            int x = 0, y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            // 計算繪製來源矩形與目標尺寸
            switch (mode.ToUpper())
            {
                case "HW": // 強制縮放
                    break;
                case "W": // 寬優先
                    toHeight = originalImage.Height * width / originalImage.Width;
                    break;
                case "H": // 高優先
                    toWidth = originalImage.Width * height / originalImage.Height;
                    break;
                case "CUT": // 裁切置中
                    double srcRatio = (double)originalImage.Width / originalImage.Height;
                    double dstRatio = (double)width / height;
                    if (srcRatio > dstRatio) // 來源較寬,裁切左右
                    {
                        oh = originalImage.Height;
                        ow = (int)(originalImage.Height * dstRatio);
                        x = (originalImage.Width - ow) / 2;
                    }
                    else // 來源較高,裁切上下
                    {
                        ow = originalImage.Width;
                        oh = (int)(originalImage.Width / dstRatio);
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    throw new ArgumentException("不支援的模式: " + mode);
            }

            // 建立目標位圖
            using (Bitmap bitmap = new Bitmap(toWidth, toHeight))
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                // 高品質設定
                g.InterpolationMode = InterpolationMode.HighQualityBicubic; // 雙三次插值
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;

                // 透明背景 (對 PNG 重要)
                g.Clear(Color.Transparent);

                // 繪製指定來源區域到目標矩形
                g.DrawImage(originalImage,
                    new Rectangle(0, 0, toWidth, toHeight),
                    new Rectangle(x, y, ow, oh),
                    GraphicsUnit.Pixel);

                // 確保目錄存在
                string dir = Path.GetDirectoryName(thumbnailPath);
                if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);

                // 儲存 (預設 JPEG,可依副檔名決定格式)
                ImageFormat format = GetImageFormat(thumbnailPath);
                bitmap.Save(thumbnailPath, format);
            }
        }
    }

    private static ImageFormat GetImageFormat(string path)
    {
        string ext = Path.GetExtension(path).ToLower();
        return ext switch
        {
            ".png" => ImageFormat.Png,
            ".gif" => ImageFormat.Gif,
            ".bmp" => ImageFormat.Bmp,
            ".tiff" => ImageFormat.Tiff,
            _ => ImageFormat.Jpeg
        };
    }
}

關鍵技術點解析

設定作用建議值
InterpolationMode縮放插值算法HighQualityBicubic (雙三次,最佳品質)
SmoothingMode向量圖形平滑度HighQuality
CompositingQuality合成品質HighQuality
PixelOffsetMode像素偏移修正HighQuality
DrawImage 來源/目標矩形精確控制裁切與縮放區域GraphicsUnit.Pixel 確保像素精度

使用範例

// 1. 固定 200x200 強制縮放
ImageHelper.MakeThumbnail(@"C:\Images\photo.jpg", @"C:\Thumbs\photo_hw.jpg", 200, 200, "HW");

// 2. 寬 300,高自適應
ImageHelper.MakeThumbnail(@"C:\Images\photo.jpg", @"C:\Thumbs\photo_w.jpg", 300, 0, "W");

// 3. 高 150,寬自適應
ImageHelper.MakeThumbnail(@"C:\Images\photo.jpg", @"C:\Thumbs\photo_h.jpg", 0, 150, "H");

// 4. 裁切置中 150x150 (適合頭像、商品列表)
ImageHelper.MakeThumbnail(@"C:\Images\photo.jpg", @"C:\Thumbs\photo_cut.jpg", 150, 150, "Cut");

常見問題與解決

  1. GDI+ 通用錯誤**:從資源檔/DB Blob 讀取 `Image` 後直接 `Save` 到 `Response.OutputStream` 會失敗。 解決:`new Bitmap(originalImage)` 建立副本再儲存。
  2. 記憶體洩漏**:`Image`、`Bitmap`、`Graphics` 實作 `IDisposable`,**務必用 `using` 區塊**確保釋放非受控資源。
  3. 權限問題**:IIS 應用程式集區身分需具備目標資料夾寫入權限。
  4. 大圖處理**:超大圖片 (如 4000x3000) 直接載入會耗盡記憶體。建議使用 `Image.GetThumbnailImageAbort` 回呼或第三方庫 (ImageMagick、SkiaSharp) 串流處理。

總結

封裝 `MakeThumbnail` 靜態方法,支援四種縮放模式、高品質插值設定、自動格式判斷與資源正確釋放,是 ASP.NET 專案處理縮略圖的標準工具類。生產環境大量圖片處理建議改用非同步佇列 + 專用圖片服務 (如 ImageSharp) 避免阻塞 Web 執行緒。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved