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

ASP.NET 縮略圖生成完整實作:GDI+ 影像處理與編碼器控制

     編輯:關於C語言

需求背景

Web 應用常需生成圖片縮略圖供列表預覽。.NET Framework 內建 System.Drawing 命名空間提供完整 GDI+ 封裝,無需第三方元件即可實現高品質縮略圖生成,支援 JPEG、PNG、TIFF、BMP 等主流格式。

核心實作類別


using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using System.Web.UI;

namespace Exam_C {
    public class ToThumbnailImage : Page {
        // 支援的副檔名與 MIME 對應
        static Hashtable htmimes = new Hashtable();
        readonly string AllowExt = ".jpe|.jpeg|.jpg|.png|.tif|.tiff|.bmp";

        protected override void OnInit(EventArgs e) {
            // 初始化 MIME 對應表
            htmimes[".jpe"] = "image/jpeg";
            htmimes[".jpeg"] = "image/jpeg";
            htmimes[".jpg"] = "image/jpeg";
            htmimes[".png"] = "image/png";
            htmimes[".tif"] = "image/tiff";
            htmimes[".tiff"] = "image/tiff";
            htmimes[".bmp"] = "image/bmp";

            // 呼叫生成範例
            ToThumbnailImages("lionsky.jpg", "b.gif", 300);
        }

        // 取得指定 MIME 的編碼器
        static ImageCodecInfo GetCodecInfo(string mimeType) {
            foreach (ImageCodecInfo ici in ImageCodecInfo.GetImageEncoders())
                if (ici.MimeType == mimeType) return ici;
            return null;
        }

        // 驗證副檔名
        bool CheckValidExt(string ext) {
            foreach (string allowed in AllowExt.Split('|'))
                if (allowed.ToLower() == ext.ToLower()) return true;
            return false;
        }

        // 儲存影像(支援品質參數)
        void SaveImage(Image image, string path, ImageCodecInfo ici) {
            EncoderParameters ep = new EncoderParameters(1);
            ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
            image.Save(path, ici, ep);
            ep.Dispose();
        }

        // 主要縮略圖生成邏輯
        public void ToThumbnailImages(string sourcePath, string thumbPath, int thumbWidth) {
            string src = sourcePath;
            string dest = thumbPath;
            int targetWidth = thumbWidth;
            string ext = src.Substring(src.LastIndexOf('.')).ToLower();

            if (string.IsNullOrEmpty(src))
                throw new NullReferenceException("SourceImagePath is null!");
            if (!CheckValidExt(ext))
                throw new ArgumentException($"不支援格式,允許: {AllowExt}", "SourceImagePath");

            // 載入原圖
            Image img = Image.FromFile(HttpContext.Current.Server.MapPath(src));
            int srcW = img.Width, srcH = img.Height;

            // 計算目標尺寸(保持比例)
            int targetHeight = (targetWidth * 3) / 4;  // 預設 4:3
            if (((double)srcW / srcH) >= 1.3333333333333333)  // 寬圖
                targetHeight = (srcH * targetWidth) / srcW;
            else  // 高圖
                targetWidth = (srcW * targetHeight) / srcH;

            if (targetWidth < 1 || targetHeight < 1) return;

            // 建立高品質畫布
            Bitmap bmp = new Bitmap(targetWidth, targetHeight, PixelFormat.Format32bppArgb);
            using (Graphics g = Graphics.FromImage(bmp)) {
                g.Clear(Color.Transparent);
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(img, new Rectangle(0, 0, targetWidth, targetHeight));
            }
            img.Dispose();

            try {
                string savePath = string.IsNullOrEmpty(dest) ? src : dest;
                SaveImage(bmp, HttpContext.Current.Server.MapPath(savePath), GetCodecInfo((string)htmimes[ext]));
            } finally {
                bmp.Dispose();
            }
        }
    }
}

關鍵技術點解析

1. 編碼器品質控制


EncoderParameters ep = new EncoderParameters(1);
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);  // 90% 品質
image.Save(path, ici, ep);

JPEG 壓縮品質 90% 通常在檔案大小與視覺品質間取得最佳平衡。

2. 高品質縮放插值


g.InterpolationMode = InterpolationMode.HighQualityBicubic;

雙三次插值比預設雙線性插值產生更銳利、較少鋸齒的縮略圖。

3. 透明背景支援


Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);  // 32-bit 帶 Alpha
g.Clear(Color.Transparent);

保留 PNG 透明通道,避免白底干擾。

4. 資源釋放模式


using (Graphics g = Graphics.FromImage(bmp)) { ... }  // 確保 Graphics 釋放
img.Dispose();  // 釋放原圖非受控資源
bmp.Dispose();  // 釋放目標位圖

GDI+ 物件包裝非受控記憶體,必須明確 Dispose,避免記憶體洩漏與 GDI+ 物件耗盡。

ASPX 頁面整合


<%@ Page Language="c#" Codebehind="ToThumbnailImage.aspx.cs" 
    Src="ToThumbnailImage.aspx.cs" AutoEventWireup="false" 
    Inherits="Exam_C.ToThumbnailImage" %>
生成縮略圖

生產環境強化建議

議題解決方案
效能瓶頸引入快取機制(記憶體/磁碟/Redis),避免重複生成
大圖記憶體壓力使用 Image.GetThumbnailImageAbort 回調或分塊處理
併發存取檔案鎖定或快取雙重檢查鎖定
格式擴充加入 WebP、AVIF 支援(需外部庫)
安全性驗證檔案魔數而非僅副檔名,防惡意上傳
雲端部署Azure Functions / AWS Lambda 無伺服器縮圖服務

總結

System.Drawing 提供完整伺服器端影像處理能力,配合編碼器參數控制、插值模式選擇、資源正確釋放,可構建穩健的縮略圖生成服務。現代雲原生架構建議將影像處理剝離為獨立微服務,採用 ImageSharp、SkiaSharp 等跨平台庫替代 Windows 專屬的 GDI+ 封裝。

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