在 ASP.NET 中利用 System.Drawing (GDI+) 將文字渲染為圖片,常用於驗證碼、動態水印、個人化簽名檔、圖表標籤等場景。注意:System.Drawing 在 Linux/容器環境需安裝 libgdiplus,且非執行緒安全,高併發建議改用 ImageSharp、SkiaSharp 等跨平台庫。
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
public class TextToImageRenderer
{
///
/// 將文字繪製成 JPEG 圖片
///
/// 要繪製的文字
/// 輸出完整路徑
/// 圖片寬度
/// 圖片高度
/// 字型名稱
/// 字型大小
/// 字型樣式
/// 文字顏色
/// 背景顏色
/// 文字對齊
public void CreateImage(
string text,
string outputPath,
int width = 400,
int height = 200,
string fontFamily = "Arial",
float fontSize = 48,
FontStyle fontStyle = FontStyle.Bold,
Color? textColor = null,
Color? backColor = null,
StringAlignment textAlign = StringAlignment.Center)
{
using (Bitmap bitmap = new Bitmap(width, height))
using (Graphics g = Graphics.FromImage(bitmap))
{
// 高品質設定
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
// 背景
g.Clear(backColor ?? ColorTranslator.FromHtml("#f0f0f0"));
// 字型與筆刷
using (Font font = new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel))
using (SolidBrush brush = new SolidBrush(textColor ?? Color.Black))
{
// 版面區域
RectangleF layoutRect = new RectangleF(0, 0, width, height);
StringFormat format = new StringFormat
{
Alignment = textAlign,
LineAlignment = StringAlignment.Center,
Trimming = StringTrimming.EllipsisCharacter
};
// 繪製文字
g.DrawString(text, font, brush, layoutRect, format);
}
// 儲存 JPEG,品質 90%
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
bitmap.Save(outputPath, jpegCodec, encoderParams);
}
}
private ImageCodecInfo GetEncoderInfo(string mimeType)
{
return ImageCodecInfo.GetImageEncoders()
.FirstOrDefault(c => c.MimeType == mimeType);
}
}
public ActionResult GenerateTextImage(string text = "Hello")
{
using (var bitmap = new Bitmap(300, 100))
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
using (var font = new Font("Microsoft JhengHei", 24, FontStyle.Bold))
using (var brush = new SolidBrush(Color.DarkBlue))
{
g.DrawString(text, font, brush, new PointF(10, 30));
}
using (var ms = new MemoryStream())
{
bitmap.Save(ms, ImageFormat.Png);
return File(ms.ToArray(), "image/png");
}
}
}
前端直接使用:<img src="/Home/GenerateTextImage?text=Hello%20World" />
public class CaptchaGenerator
{
private const string Chars = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
private readonly Random _rng = new Random();
public (string Code, byte[] ImageBytes) Generate(int length = 4, int width = 120, int height = 40)
{
string code = new string(Enumerable.Range(0, length).Select(_ => Chars[_rng.Next(Chars.Length)]).ToArray());
using (var bmp = new Bitmap(width, height))
using (var g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
g.SmoothingMode = SmoothingMode.AntiAlias;
// 背景雜訊
for (int i = 0; i < 20; i++)
{
using (var pen = new Pen(Color.FromArgb(_rng.Next(150, 220), _rng.Next(150, 220), _rng.Next(150, 220)), 1))
{
g.DrawLine(pen, _rng.Next(width), _rng.Next(height), _rng.Next(width), _rng.Next(height));
}
}
// 文字 (逐字隨機位移/旋轉)
using (var font = new Font("Arial", 22, FontStyle.Bold | FontStyle.Italic))
using (var brush = new SolidBrush(Color.FromArgb(_rng.Next(0, 100), _rng.Next(0, 100), _rng.Next(0, 100))))
{
float x = 5;
for (int i = 0; i < code.Length; i++)
{
var state = g.Save();
g.TranslateTransform(x + 15, height / 2f);
g.RotateTransform(_rng.Next(-15, 15));
g.DrawString(code[i].ToString(), font, brush, -10, -12);
g.Restore(state);
x += 25;
}
}
using (var ms = new MemoryStream())
{
bmp.Save(ms, ImageFormat.Png);
return (code, ms.ToArray());
}
}
}
}
| 庫 | 優點 | 適用場景 |
|---|---|---|
| ImageSharp | 純 managed、跨平台、執行緒安全、API 現代 | ASP.NET Core、Linux 容器、Serverless |
| SkiaSharp | Google Skia 引擎、效能極佳、功能豐富 | 高併發、複雜繪圖、PDF 生成 |
| QuestPDF | 流式版面、支援中文、適合報表/文件 | 動態 PDF/圖片報表 |
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.Fonts;
public byte[] GenerateWithImageSharp(string text)
{
var font = SystemFonts.CreateFont("Arial", 48, FontStyle.Bold);
var options = new TextOptions(font) { Origin = new PointF(10, 10), HorizontalAlignment = HorizontalAlignment.Left };
// 自動測量文字大小
var textSize = TextMeasurer.MeasureSize(text, options);
int width = (int)textSize.Width + 20;
int height = (int)textSize.Height + 20;
using (var img = new Image(width, height, Color.LightGray))
{
img.Mutate(ctx => ctx.DrawText(options, text, Color.Black));
using (var ms = new MemoryStream())
{
img.SaveAsPng(ms);
return ms.ToArray();
}
}
}
System.Drawing 即可滿足基本需求。using 釋放非受控資源 (GDI+ 物件、記憶體流)。