Web 應用常需動態產生帶有特殊字體、陰影、透明度、背景圖的文字圖片(如驗證碼、水印、標題圖)。利用 System.Drawing 命名空間下的 Bitmap、Graphics 即可完整實現。
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
public class Watermark
{
// 屬性(省略 getter/setter,僅列關鍵屬性)
public int Width { get; set; } = 460;
public int Height { get; set; } = 30;
public string FontFamily { get; set; } = "華文行楷";
public int FontSize { get; set; } = 20;
public FontStyle FontStyle { get; set; } = FontStyle.Regular;
public bool Adaptable { get; set; } = true; // 自動縮放
public bool Shadow { get; set; } = false;
public string BackgroundImage { get; set; } = "";
public Color BgColor { get; set; } = Color.FromArgb(255, 229, 229, 229);
public int Left { get; set; } = 0;
public int Top { get; set; } = 0;
public int Alpha { get; set; } = 255;
public int Red { get; set; } = 0;
public int Green { get; set; } = 0;
public int Blue { get; set; } = 0;
public long Quality { get; set; } = 100;
public string Text { get; set; } = "";
public string ResultImage { get; set; } = "";
public bool Create()
{
try
{
Bitmap bitmap;
Graphics g;
// 1. 建立畫布:純色或背景圖
if (string.IsNullOrWhiteSpace(BackgroundImage))
{
bitmap = new Bitmap(Width, Height, PixelFormat.Format64bppArgb);
g = Graphics.FromImage(bitmap);
g.Clear(BgColor);
}
else
{
bitmap = new Bitmap(Image.FromFile(BackgroundImage));
g = Graphics.FromImage(bitmap);
// 實際寬高以背景圖為準
Width = bitmap.Width;
Height = bitmap.Height;
}
// 2. 高品質繪圖設定
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
// 3. 字體與自動縮放
Font font = new Font(FontFamily, FontSize, FontStyle);
SizeF textSize = g.MeasureString(Text, font);
while (Adaptable && textSize.Width > bitmap.Width && FontSize > 1)
{
FontSize--;
font = new Font(FontFamily, FontSize, FontStyle);
textSize = g.MeasureString(Text, font);
}
// 4. 畫刷與格式
Brush brush = new SolidBrush(Color.FromArgb(Alpha, Red, Green, Blue));
StringFormat fmt = new StringFormat { Alignment = StringAlignment.Near };
// 5. 陰影優先繪製
if (Shadow)
{
Brush shadowBrush = new SolidBrush(Color.FromArgb(90, 0, 0, 0));
g.DrawString(Text, font, shadowBrush, Left + 2, Top + 1);
}
// 6. 繪製主文字
g.DrawString(Text, font, brush, new PointF(Left, Top), fmt);
// 7. 儲存 JPEG
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, Quality);
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
bitmap.Save(ResultImage, jpegCodec, encoderParams);
// 8. 釋放資源
brush.Dispose();
if (Shadow) ((IDisposable)g).Dispose(); // 陰影筆刷已在上方
font.Dispose();
g.Dispose();
bitmap.Dispose();
return true;
}
catch
{
return false;
}
}
private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
foreach (var codec in ImageCodecInfo.GetImageEncoders())
if (codec.MimeType == mimeType) return codec;
return null;
}
}
var wm = new Watermark
{
Width = 600,
Height = 100,
Text = "動態產生文字圖片測試",
FontFamily = "微軟正黑體",
FontSize = 36,
FontStyle = FontStyle.Bold,
Red = 255, Green = 0, Blue = 0, Alpha = 200,
Shadow = true,
Left = 20, Top = 20,
BgColor = Color.White,
ResultImage = @"C:\Temp\watermark.jpg",
Quality = 90
};
bool ok = wm.Create();
Console.WriteLine(ok ? "產生成功" : "產生失敗");
FontFamily 指定的字體需存在於 Web 伺服器作業系統,否則會回退預設字體。Dispose() 所有 Bitmap、Graphics、Font、Brush 物件,建議使用 using 區塊。libgdiplus 並啟用 System.Drawing.Common 相容性,或改用跨平台庫 ImageSharp、SkiaSharp。