核心類:ToThumbnailImage
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using System.Collections;
public class ToThumbnailImage : System.Web.UI.Page
{
// 支持格式映射
static readonly Hashtable MimeTypes = new Hashtable
{
{".jpe", "image/jpeg"}, {".jpeg", "image/jpeg"}, {".jpg", "image/jpeg"},
{".png", "image/png"}, {".tif", "image/tiff"}, {".tiff", "image/tiff"}, {".bmp", "image/bmp"}
};
readonly string AllowExt = ".jpe|.jpeg|.jpg|.png|.tif|.tiff|.bmp";
// 獲取編碼器
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 e in AllowExt.Split('|'))
if (e.Equals(ext, StringComparison.OrdinalIgnoreCase)) return true;
return false;
}
// 保存圖片(質量 90%)
void SaveImage(Image img, string path, ImageCodecInfo ici)
{
using (EncoderParameters ep = new EncoderParameters(1))
{
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
img.Save(path, ici, ep);
}
}
// 主入口
public void ToThumbnailImages(string sourcePath, string thumbPath, int thumbWidth)
{
string src = sourcePath;
string dst = thumbPath ?? sourcePath;
int targetW = thumbWidth;
string ext = System.IO.Path.GetExtension(src).ToLower();
if (string.IsNullOrEmpty(src)) throw new ArgumentNullException(nameof(sourcePath));
if (!CheckValidExt(ext)) throw new ArgumentException($"不支持的格式:{ext},允許:{AllowExt}");
using (Image srcImg = Image.FromFile(HttpContext.Current.Server.MapPath(src)))
{
int srcW = srcImg.Width, srcH = srcImg.Height;
// 計算目標高度,保持比例
int targetH = (int)(srcH * targetW / (double)srcW);
if (targetW < 1 || targetH < 1) return;
using (Bitmap bmp = new Bitmap(targetW, targetH, PixelFormat.Format32bppArgb))
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Transparent);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(srcImg, new Rectangle(0, 0, targetW, targetH));
string savePath = HttpContext.Current.Server.MapPath(dst);
SaveImage(bmp, savePath, GetCodecInfo((string)MimeTypes[ext]));
}
}
}
}
關鍵技術點
- 比例縮放:按寬度計算高度,防止變形。
- 高質量插值:
InterpolationMode.HighQualityBicubic 雙三次插值,縮放效果最佳。
- 格式保持:根據原圖 MIME 類型選擇對應編碼器,保留原格式特性。
- 質量控制:JPEG 質量 90% 平衡體積與清晰度。
- 資源釋放:全程
using 確保 Image/Graphics/EncoderParameters 及時釋放。
調用示例
// 在 Page_Load 或 Handler 中
new ToThumbnailImage().ToThumbnailImages("~/images/photo.jpg", "~/thumbs/photo.jpg", 300);
遷移至 .NET Core / 5+ 建議
- 移除
System.Web 依賴,改用 IWebHostEnvironment 解析物理路徑。
- 引用
System.Drawing.Common NuGet 包(僅 Windows 完整支持,Linux 需安裝 libgdiplus)。
- 考慮使用
ImageSharp、SkiaSharp 等跨平台圖像庫替代 GDI+。