ColorMatrix 實作 Alpha 混合,效能佳、品質高。public class PicMark {
public string ModifyImagePath { get; set; } // 來源圖片路徑
public string DrawedImagePath { get; set; } // 水印圖片路徑
public int RightSpace { get; set; } // 距右邊界像素
public int BottomSpace { get; set; } // 距下邊界像素
public int LucencyPercent { get; set; } = 70; // 透明度 0-100
public string OutPath { get; set; } // 輸出路徑,null 覆蓋原檔
public void DrawImage() { ... }
}
// 前台上傳
<asp:FileUpload ID="fuImg" runat="server" />
<asp:Button ID="btnMark" Text="加浮水印" OnClick="btnMark_Click" />
// 後台處理
protected void btnMark_Click(object sender, EventArgs e) {
string ext = Path.GetExtension(fuImg.FileName).ToUpper();
string fileName = Guid.NewGuid().ToString("N") + ext;
string savePath = Server.MapPath("~/upfile/" + fileName);
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
fuImg.SaveAs(savePath);
var wm = new PicMark {
ModifyImagePath = savePath,
DrawedImagePath = Server.MapPath("~/upfile/backlogo.gif"),
RightSpace = 145,
BottomSpace = 17,
LucencyPercent = 50,
OutPath = Server.MapPath("~/upfile/" + fileName + "_wm" + ext)
};
wm.DrawImage();
// 刪除原始上傳檔,保留加浮水印後的檔案
if (File.Exists(savePath)) File.Delete(savePath);
}
float[][] matrix = {
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, lucency/100f, 0}, // Alpha 縮放
new float[] {0, 0, 0, 0, 1}
};
ColorMatrix cm = new ColorMatrix(matrix);
ImageAttributes attr = new ImageAttributes();
attr.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
g.DrawImage(watermark, destRect, 0, 0, wm.Width, wm.Height, GraphicsUnit.Pixel, attr);
Alpha 值 1.0 = 完全不透明,0.0 = 完全透明。lucency/100f 直接對應使用者設定的百分比。
string[] allow = { ".jpg", ".gif", ".png", ".bmp", ".tif", ".wmf", ".ico" };
ImageFormat fmt = ImageFormat.Gif; // 預設
switch (ext.ToLower()) {
case ".jpg": fmt = ImageFormat.Jpeg; break;
case ".png": fmt = ImageFormat.Png; break;
// ...
}
// 先存 MemoryStream 再寫檔,避免 GDI+ 通用錯誤
using (MemoryStream ms = new MemoryStream()) {
img.Save(ms, fmt);
byte[] data = ms.ToArray();
// 寫入 FileStream
}
Image、Graphics、Stream 均在 finally 區塊呼叫 Dispose()。Dispose 來源 Image,釋放檔案鎖定,才能覆蓋寫入。G.DrawString 區段,加入字型、顏色、陰影參數。DrawImage 回傳 Bitmap,支援鏈式呼叫疊加多層水印。Task.Run 或背景佇列(Hangfire/Quartz)。OutPath 改為 Stream 參數,直接上傳至 Azure Blob / AWS S3。| 現象 | 原因 | 解決 |
|---|---|---|
| 輸出圖片變黑/全透明 | ColorMatrix Alpha 設錯 | 確認 LucencyPercent 0~100,矩陣第 4 列第 4 行為 percent/100f |
| GDI+ 通用錯誤 | 檔案被佔用或格式不支援 | 先存 MemoryStream,確認副檔名對應 ImageFormat |
| 水印位置偏移 | 座標計算未考慮圖片寬高 | x = src.Width - rightSpace - wm.Width(程式碼已內建) |