绘制文字水印需按图片短边3%~5%动态计算字号并校正dpi,启用antialiasgridfit抗锯齿,用alpha控制透明度;logo叠加须确保png带alpha通道、保持宽高比缩放并及时dispose;jpeg保存需指定高质量编码器与srgb配置,批量处理须全程显式释放资源。

用 Graphics 绘制文字水印时字体缩放容易失真
直接用 Graphics.DrawString 往原图上画文字,看似简单,但常见问题是:小图上文字糊成一片、大图上又细得看不清。根本原因是没做 DPI 适配和字体大小归一化。
- 别硬写固定字号(比如
new Font("Arial", 12)),改用相对尺寸:按图片短边的 3%~5% 计算字号,再用graphics.DpiX和DpiY校正 - 开启抗锯齿:
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit,否则中文边缘毛刺明显 - 文字透明度靠
Color.FromArgb(100, 0, 0, 0)控制 Alpha 值,别用Brushes.Gray这类不透明预设 - 记得调用
graphics.TranslateTransform()配合旋转,否则斜水印会切掉边缘
叠加 Logo 图片水印必须处理透明通道和缩放比例
直接 Graphics.DrawImage 贴 PNG Logo,常出现白底、锯齿、拉伸变形——本质是没区分图像类型和像素格式。
- 源 Logo 必须是带 Alpha 通道的 PNG,加载后检查
logo.PixelFormat是否含Format32bppArgb - 缩放不用
DrawImage(destRect)粗暴拉伸,改用DrawImage(logosrc, destRect, srcRect, GraphicsUnit.Pixel)并手动计算srcRect保持宽高比 - 避免内存泄漏:Logo
Bitmap实例用完立即Dispose(),尤其在循环加水印时 - 如果目标图是 JPEG,叠加前先转成
PixelFormat.Format32bppArgb,否则透明区域会变黑
Image.Save 保存时质量丢失严重
保存后的水印图发灰、文字边缘泛白、Logo 边缘有光晕——八成是 JPEG 编码质量或颜色空间没控住。
- 别用默认
image.Save(path),必须指定编码器和参数:image.Save(path, GetJpegEncoder(), jpegParams) -
jpegParams中Encoder.Quality设为 90~95,低于 80 文字细节就糊了 - 强制输出 sRGB:在保存前对 Bitmap 调用
bitmap.SetResolution(96, 96),并确保原始图元数据没带 Adobe RGB 配置文件 - 如果原图是 PNG,保留透明背景就别转 JPEG,直接用
ImageFormat.Png保存
批量处理时 GDI+ 内存暴涨甚至崩溃
循环给几百张图加水印,跑一半报 OutOfMemoryException 或“GDI+ 中发生一般性错误”——这是 .NET 对 GDI+ 句柄数限制触发的典型问题。
- 所有
Bitmap、Graphics、Font、Brush实例,必须用using包裹或显式Dispose() - 别复用同一个
Graphics实例跨图操作;每张图都新建Graphics.FromImage(),用完立刻释放 - 避免在循环里反复创建
Font,提取成静态只读字段(注意线程安全) - 大图(>5000px 边长)先缩略再加水印,处理完再还原尺寸,比硬扛内存更稳
Dispose() 的时机和 PixelFormat 的校验,这两处一漏,问题要么延迟爆发,要么只在特定图片上出现。











