ImageWatermarker.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System;
  2. using SixLabors.Fonts;
  3. using SixLabors.ImageSharp;
  4. using SixLabors.ImageSharp.Drawing.Processing;
  5. using SixLabors.ImageSharp.Processing;
  6. using System.IO;
  7. using System.Text;
  8. using SixLabors.ImageSharp.Processing.Processors.Transforms;
  9. namespace Masuit.Tools.Media
  10. {
  11. public class ImageWatermarker
  12. {
  13. /// <summary>
  14. /// 是否跳过小缩略图
  15. /// </summary>
  16. public bool SkipWatermarkForSmallImages { get; set; }
  17. /// <summary>
  18. /// 小图像素大小
  19. /// </summary>
  20. public int SmallImagePixelsThreshold { get; set; }
  21. private readonly Stream _stream;
  22. public ImageWatermarker(Stream originStream)
  23. {
  24. _stream = originStream;
  25. }
  26. public MemoryStream AddWatermark(string watermarkText, string ttfFontPath, int fontSize, Color color, WatermarkPosition watermarkPosition = WatermarkPosition.BottomRight, int textPadding = 10)
  27. {
  28. var fonts = new FontCollection();
  29. var fontFamily = fonts.Add(ttfFontPath); //字体的路径(电脑自带字体库,去copy出来)
  30. var font = new Font(fontFamily, fontSize, FontStyle.Bold);
  31. return AddWatermark(watermarkText, font, color, watermarkPosition, textPadding);
  32. }
  33. /// <summary>
  34. /// 添加水印
  35. /// </summary>
  36. /// <param name="watermarkText">水印文字</param>
  37. /// <param name="color">水印颜色</param>
  38. /// <param name="watermarkPosition">水印位置</param>
  39. /// <param name="textPadding">边距</param>
  40. /// <param name="font">字体</param>
  41. /// <returns></returns>
  42. public MemoryStream AddWatermark(string watermarkText, Font font, Color color, WatermarkPosition watermarkPosition = WatermarkPosition.BottomRight, int textPadding = 10)
  43. {
  44. using var img = Image.Load(_stream);
  45. var textMeasure = TextMeasurer.Measure(watermarkText, new TextOptions(font));
  46. if (SkipWatermarkForSmallImages && (img.Height < Math.Sqrt(SmallImagePixelsThreshold) || img.Width < Math.Sqrt(SmallImagePixelsThreshold) || img.Width <= textMeasure.Width))
  47. {
  48. return _stream as MemoryStream ?? _stream.SaveAsMemoryStream();
  49. }
  50. if (img.Width / font.Size > 50)
  51. {
  52. font = font.Family.CreateFont(img.Width * 1f / 50);
  53. }
  54. float x, y;
  55. textPadding += (img.Width - 1000) / 100;
  56. switch (watermarkPosition)
  57. {
  58. case WatermarkPosition.TopRight:
  59. x = img.Width - textMeasure.Width - textPadding;
  60. y = textPadding;
  61. break;
  62. case WatermarkPosition.BottomLeft:
  63. x = textPadding;
  64. y = img.Height - textMeasure.Height - textPadding;
  65. break;
  66. case WatermarkPosition.BottomRight:
  67. x = img.Width - textMeasure.Width - textPadding;
  68. y = img.Height - textMeasure.Height - textPadding;
  69. break;
  70. case WatermarkPosition.Center:
  71. x = (img.Width - textMeasure.Width) / 2;
  72. y = (img.Height - textMeasure.Height) / 2;
  73. break;
  74. default:
  75. x = textPadding;
  76. y = textPadding;
  77. break;
  78. }
  79. img.Mutate(c => c.DrawText(watermarkText, font, color, new PointF(x, y)));
  80. var ms = new MemoryStream();
  81. img.SaveAsWebp(ms);
  82. ms.Position = 0;
  83. return ms;
  84. }
  85. /// <summary>
  86. /// 添加水印
  87. /// </summary>
  88. /// <param name="watermarkImage">水印图片</param>
  89. /// <param name="opacity">水印图片</param>
  90. /// <param name="watermarkPosition">水印位置</param>
  91. /// <param name="padding">水印边距</param>
  92. /// <returns></returns>
  93. public MemoryStream AddWatermark(Stream watermarkImage, float opacity = 1f, WatermarkPosition watermarkPosition = WatermarkPosition.BottomRight, int padding = 20)
  94. {
  95. using var img = Image.Load(_stream);
  96. var height = img.Height;
  97. var width = img.Width;
  98. if (SkipWatermarkForSmallImages && (height < Math.Sqrt(SmallImagePixelsThreshold) || width < Math.Sqrt(SmallImagePixelsThreshold)))
  99. {
  100. return _stream as MemoryStream ?? _stream.SaveAsMemoryStream();
  101. }
  102. var watermark = Image.Load(watermarkImage);
  103. watermark.Mutate(c => c.Resize(new ResizeOptions()
  104. {
  105. Size = new Size
  106. {
  107. Width = width / 10,
  108. Height = height / 10,
  109. },
  110. Mode = ResizeMode.Pad,
  111. Sampler = new BicubicResampler()
  112. }));
  113. int x, y;
  114. padding += (width - 1000) / 100;
  115. switch (watermarkPosition)
  116. {
  117. case WatermarkPosition.TopRight:
  118. x = width - watermark.Width - padding;
  119. y = padding;
  120. break;
  121. case WatermarkPosition.BottomLeft:
  122. x = padding;
  123. y = height - watermark.Height - padding;
  124. break;
  125. case WatermarkPosition.BottomRight:
  126. x = width - watermark.Width - padding;
  127. y = height - watermark.Height - padding;
  128. break;
  129. case WatermarkPosition.Center:
  130. x = (img.Width - watermark.Width) / 2;
  131. y = (img.Height - watermark.Height) / 2;
  132. break;
  133. default:
  134. x = padding;
  135. y = padding;
  136. break;
  137. }
  138. img.Mutate(c =>
  139. {
  140. c.DrawImage(watermark, new Point(x, y), opacity);
  141. watermark.Dispose();
  142. });
  143. var ms = new MemoryStream();
  144. img.SaveAsWebp(ms);
  145. ms.Position = 0;
  146. return ms;
  147. }
  148. }
  149. }