功能流程
- 原圖縮略至寬或高 90px
- 用戶選區裁剪 90×90 區域
- 套用水晶效果(漸變、陰影、高光)輸出 PNG
核心實現代碼
public static void Avatar(Page page, string filename, int r, int m, int s, int x, int y, bool save, string newAvatarPath)
{
var imageSrc = Image.FromFile(HttpContext.Current.Server.MapPath("/") + filename);
int w = imageSrc.Width, h = imageSrc.Height;
// 旋轉/翻轉參數處理
if (r == 1 || r == 3) { h = imageSrc.Width; w = imageSrc.Height; }
if (save) { w = h = 90; }
if (w > 300) w = 300;
if (h > 300) h = 300;
var backColor = Color.DarkTurquoise;
var size = new Size(w, h);
var btnBmp = new Bitmap(w, h);
var g = Graphics.FromImage(btnBmp);
g.Clear(Color.White);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
int btnOff = 0;
var rc1 = new Rectangle(btnOff, btnOff, size.Width - 1 - btnOff, size.Height - 1 - btnOff);
var gpath1 = GetGraphicsPath(rc1, 10);
var gpath1a = GetGraphicsPath(rc1, 15);
var br1 = new LinearGradientBrush(new Point(0, 0), new Point(0, rc1.Height + 6), backColor, Color.White);
// 陰影
int shadowOff = 1;
var rc2 = rc1; rc2.Offset(0, shadowOff);
var gpath2 = GetGraphicsPath(rc2, 10);
var br2 = new PathGradientBrush(gpath2);
br2.CenterColor = Color.FromArgb(0, 0, 0);
br2.SurroundColors = new[] { Color.FromArgb(64, 64, 64, 64), Color.FromArgb(64, 128, 128, 128) };
// 頂部高光
var rc3 = rc1; rc3.Inflate(-1, -1); rc3.Height = 15;
var gpath3 = GetGraphicsPath(rc3, 10);
var br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical);
// 繪製順序:陰影 → 底色 → 裁剪區域 → 圖片 → 高光
if (s > 0) g.FillPath(br2, gpath2);
if (s > 0) g.FillPath(br1, gpath1);
g.SetClip(gpath1a, CombineMode.Replace);
// 圖片變換
switch (m) {
case 1: imageSrc.RotateFlip(RotateFlipType.RotateNoneFlipX); break;
case 2: imageSrc.RotateFlip(RotateFlipType.RotateNoneFlipY); break;
}
switch (r) {
case 1: imageSrc.RotateFlip(RotateFlipType.Rotate90FlipNone); break;
case 2: imageSrc.RotateFlip(RotateFlipType.Rotate180FlipNone); break;
case 3: imageSrc.RotateFlip(RotateFlipType.Rotate270FlipNone); break;
}
g.DrawImage(imageSrc, -x, -y);
if (s > 0) g.FillPath(br3, gpath3);
imageSrc.Dispose(); g.Dispose();
// 輸出
using (var ms = new MemoryStream()) {
btnBmp.Save(ms, ImageFormat.Png);
if (save) {
btnBmp.Save(HttpContext.Current.Server.MapPath("/") + newAvatarPath);
}
OutputImage(page, ms);
}
}
private static void OutputImage(Page page, MemoryStream ms) {
page.Response.Expires = 0;
page.Response.ExpiresAbsolute = DateTime.Now.AddSeconds(-1);
page.Response.AddHeader("pragma", "no-cache");
page.Response.CacheControl = "no-cache";
page.Response.Clear();
page.Response.ContentType = "image/png";
page.Response.BinaryWrite(ms.ToArray());
}
// 輔助:圓角矩形路徑
private static GraphicsPath GetGraphicsPath(Rectangle rect, int radius) {
var path = new GraphicsPath();
int d = radius * 2;
path.AddArc(rect.X, rect.Y, d, d, 180, 90);
path.AddArc(rect.Right - d, rect.Y, d, d, 270, 90);
path.AddArc(rect.Right - d, rect.Bottom - d, d, d, 0, 90);
path.AddArc(rect.X, rect.Bottom - d, d, d, 90, 90);
path.CloseFigure();
return path;
}
關鍵技術點
GraphicsPath + LinearGradientBrush 實現圓角漸變底色
PathGradientBrush 產生立體陰影效果
SetClip 限制圖片顯示在圓角區域內
- 高質量插值模式保證縮放清晰度
- 支持旋轉、翻轉、平移參數,配合前端裁剪組件使用