在 ASP.NET Web Forms 專案中,圖片上傳與縮略圖生成是常見需求。許多開發者面臨縮略圖模糊、失真或尺寸過大的問題。本文提供一套完整的上傳與兩階段縮放演算法,能產生接近繪圖軟體品質的高清縮略圖。
////// ASP.NET 上傳圖片並生成高畫質縮略圖 /// /// HtmlInputFile 控制項 /// 相對伺服器儲存路徑 /// 縮略圖檔名前綴 /// 縮略圖寬度 /// 縮略圖高度 ///縮略圖檔名 public string UpLoadImage(HtmlInputFile upImage, string sSavePath, string sThumbExtension, int intThumbWidth, int intThumbHeight) { string sThumbFile = "", sFilename = ""; if (upImage.PostedFile == null) return "未選擇圖片"; HttpPostedFile myFile = upImage.PostedFile; int nFileLen = myFile.ContentLength; if (nFileLen == 0) return "未選擇上傳圖片"; // 驗證副檔名 string extendName = System.IO.Path.GetExtension(myFile.FileName).ToLower(); if (extendName != ".jpg" && extendName != ".jpeg" && extendName != ".gif" && extendName != ".bmp" && extendName != ".png") return "圖片格式不正確"; // 讀取檔案位元組 byte[] myData = new Byte[nFileLen]; myFile.InputStream.Read(myData, 0, nFileLen); sFilename = System.IO.Path.GetFileName(myFile.FileName); // 避免同名檔案覆蓋 int file_append = 0; while (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(sSavePath + sFilename))) { file_append++; sFilename = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) + file_append.ToString() + extendName; } // 儲存原圖 string fullPath = System.Web.HttpContext.Current.Server.MapPath(sSavePath + sFilename); using (var newFile = new System.IO.FileStream(fullPath, System.IO.FileMode.Create, System.IO.FileAccess.Write)) { newFile.Write(myData, 0, myData.Length); } try { // === 兩階段縮放演算法 === using (var sourceImage = System.Drawing.Image.FromFile(fullPath)) { int width = sourceImage.Width; int height = sourceImage.Height; int smallWidth, smallHeight; // 第一階段:等比例縮放至符合目標長寬比的中間尺寸 if (((decimal)width) / height <= ((decimal)intThumbWidth) / intThumbHeight) { smallWidth = intThumbWidth; smallHeight = intThumbWidth * height / width; } else { smallWidth = intThumbHeight * width / height; smallHeight = intThumbHeight; } // 產生中間圖(高品質插值) using (var bitmap = new System.Drawing.Bitmap(smallWidth, smallHeight)) using (var g = System.Drawing.Graphics.FromImage(bitmap)) { g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.Clear(System.Drawing.Color.White); g.DrawImage(sourceImage, new System.Drawing.Rectangle(0, 0, smallWidth, smallHeight), new System.Drawing.Rectangle(0, 0, width, height), System.Drawing.GraphicsUnit.Pixel); } // 第二階段:從中間圖裁切至目標尺寸(置中裁切) file_append = 0; sThumbFile = sThumbExtension + System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) + extendName; while (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(sSavePath + sThumbFile))) { file_append++; sThumbFile = sThumbExtension + System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) + file_append.ToString() + extendName; } string smallImagePath = System.Web.HttpContext.Current.Server.MapPath(sSavePath) + sThumbFile; using (var bitmap1 = new System.Drawing.Bitmap(intThumbWidth, intThumbHeight)) using (var g = System.Drawing.Graphics.FromImage(bitmap1)) { g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.Clear(System.Drawing.Color.White); int lwidth = (smallWidth - intThumbWidth) / 2; int bheight = (smallHeight - intThumbHeight) / 2; g.DrawImage(bitmap, new System.Drawing.Rectangle(0, 0, intThumbWidth, intThumbHeight), lwidth, bheight, intThumbWidth, intThumbHeight, System.Drawing.GraphicsUnit.Pixel); bitmap1.Save(smallImagePath, System.Drawing.Imaging.ImageFormat.Jpeg); } } return sThumbFile; } catch { // 發生錯誤時刪除已上傳的原圖 System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(sSavePath + sFilename)); return "圖片處理失敗"; } }
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>圖片上傳測試
protected void Button1_Click(object sender, EventArgs e) {
string thumbName = this.UpLoadImage(this.File1, "UpLoad/", "thumb_", 118, 118);
// thumbName 即為生成的縮略圖檔名
}
若原圖極大(如 5000×5000)需縮至極小(100×80),單次縮放易產生鋸齒。可採用多階段漸進縮放:
中間圖層數越多,最終畫質越接近專業繪圖軟體輸出效果。