ImageWatermarker.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Text;
  4. using System.IO;
  5. namespace Masuit.Tools.Media
  6. {
  7. public class ImageWatermarker
  8. {
  9. /// <summary>
  10. /// 是否跳过小缩略图
  11. /// </summary>
  12. public bool SkipWatermarkForSmallImages { get; set; }
  13. /// <summary>
  14. /// 小图像素大小
  15. /// </summary>
  16. public int SmallImagePixelsThreshold { get; set; }
  17. private readonly Stream _stream;
  18. [Obsolete(nameof(ImageWatermarker) + "是基于System.Drawing实现的,System.Drawing将在.NET7开始只支持Windows下运行,如果您的项目需要在Linux下部署,请考虑使用ImageSharp或SkiaSharp之类的替代类库重新实现")]
  19. public ImageWatermarker(Stream originStream)
  20. {
  21. _stream = originStream;
  22. }
  23. /// <summary>
  24. /// 添加水印
  25. /// </summary>
  26. /// <param name="watermarkText">水印文字</param>
  27. /// <param name="color">水印颜色</param>
  28. /// <param name="watermarkPosition">水印位置</param>
  29. /// <param name="textPadding">边距</param>
  30. /// <param name="fontSize">字体大小</param>
  31. /// <param name="font">字体</param>
  32. /// <param name="textAntiAlias">不提示的情况下使用抗锯齿标志符号位图来绘制每个字符。
  33. /// 由于抗锯齿质量就越好。
  34. /// 因为关闭了提示,词干宽度之间的差异可能非常明显。</param>
  35. /// <returns></returns>
  36. [Obsolete(nameof(ImageWatermarker) + "." + nameof(AddWatermark) + "是基于System.Drawing实现的,System.Drawing将在.NET7开始只支持Windows下运行,如果您的项目需要在Linux下部署,请考虑使用ImageSharp或SkiaSharp之类的替代类库重新实现")]
  37. public MemoryStream AddWatermark(string watermarkText, Color color, WatermarkPosition watermarkPosition = WatermarkPosition.BottomRight, int textPadding = 10, int fontSize = 20, Font font = null, bool textAntiAlias = true)
  38. {
  39. using var img = Image.FromStream(_stream);
  40. if (SkipWatermarkForSmallImages && (img.Height < Math.Sqrt(SmallImagePixelsThreshold) || img.Width < Math.Sqrt(SmallImagePixelsThreshold)))
  41. {
  42. return _stream.SaveAsMemoryStream();
  43. }
  44. using var graphic = Graphics.FromImage(img);
  45. if (textAntiAlias)
  46. {
  47. graphic.TextRenderingHint = TextRenderingHint.AntiAlias;
  48. }
  49. using var brush = new SolidBrush(color);
  50. if (img.Width / fontSize > 50)
  51. {
  52. fontSize = img.Width / 50;
  53. }
  54. using var f = font ?? new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Bold, GraphicsUnit.Pixel);
  55. var textSize = graphic.MeasureString(watermarkText, f);
  56. int x, y;
  57. textPadding += (img.Width - 1000) / 100;
  58. switch (watermarkPosition)
  59. {
  60. case WatermarkPosition.TopLeft:
  61. x = textPadding;
  62. y = textPadding;
  63. break;
  64. case WatermarkPosition.TopRight:
  65. x = img.Width - (int)textSize.Width - textPadding;
  66. y = textPadding;
  67. break;
  68. case WatermarkPosition.BottomLeft:
  69. x = textPadding;
  70. y = img.Height - (int)textSize.Height - textPadding;
  71. break;
  72. case WatermarkPosition.BottomRight:
  73. x = img.Width - (int)textSize.Width - textPadding;
  74. y = img.Height - (int)textSize.Height - textPadding;
  75. break;
  76. default:
  77. x = textPadding;
  78. y = textPadding;
  79. break;
  80. }
  81. graphic.DrawString(watermarkText, f, brush, new Point(x, y));
  82. var ms = new MemoryStream();
  83. img.Save(ms, img.RawFormat);
  84. ms.Position = 0;
  85. return ms;
  86. }
  87. }
  88. }