UserAliasGenerateImageUtils.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. using SkiaSharp;
  2. using System.Globalization;
  3. using System.IO;
  4. using System;
  5. namespace JiaZhiQuan.Common.Utils
  6. {
  7. /// <summary>
  8. /// 用户昵称生成图片工具类
  9. /// </summary>
  10. public static class UserAliasGenerateImageUtils
  11. {
  12. /// <summary>
  13. /// 绘制用户昵称图片,返回流(!!!流用完自己关)
  14. /// </summary>
  15. /// <param name="dto"></param>
  16. /// <returns></returns>
  17. public static Stream Generate(UserAliasGenerateDTO dto)
  18. {
  19. // 字符串内容
  20. string text = dto.Text;
  21. // 当前内容总宽度
  22. float textSumWidth = 0;
  23. int maxEmojiWidth = dto.FontSize + 20;
  24. using var bitmap = new SKBitmap(dto.Width, dto.Height, SKColorType.Rgba8888, SKAlphaType.Premul);
  25. using var canvas = new SKCanvas(bitmap);
  26. // 创建绘图笔
  27. using var paint = new SKPaint()
  28. {
  29. Color = dto.FontColor,
  30. TextSize = dto.FontSize,
  31. // 抗锯齿
  32. IsAntialias = true,
  33. LcdRenderText = false,
  34. Style = SKPaintStyle.Fill,
  35. FilterQuality = SKFilterQuality.High
  36. };
  37. // 文字基于图片定位坐标
  38. float x = 0;
  39. float y = paint.TextSize;
  40. TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(text);
  41. while (enumerator.MoveNext())
  42. {
  43. string element = enumerator.GetTextElement();
  44. if (string.IsNullOrWhiteSpace(element))
  45. {
  46. // 如果是空格,直接计算下一次定位的x坐标即可,不需要绘制
  47. x += paint.MeasureText(element);
  48. continue;
  49. }
  50. // 判断文本元素的类型
  51. if (char.IsLetter(element[0]))
  52. {
  53. // 处理英文字符
  54. paint.Typeface = SKTypeface.FromFamilyName("Microsoft YaHei");
  55. }
  56. else if (char.IsDigit(element[0]))
  57. {
  58. // 处理数字字符
  59. paint.Typeface = SKTypeface.FromFamilyName("Microsoft YaHei");
  60. }
  61. else if (char.IsPunctuation(element[0]))
  62. {
  63. // 处理符号字符
  64. paint.Typeface = SKTypeface.FromFamilyName("Microsoft YaHei");
  65. }
  66. else
  67. {
  68. // 处理其他字符(如中文字符和 Emoji)
  69. if (CheckStringChineseUn(element))
  70. {
  71. paint.Typeface = SKTypeface.FromFamilyName("Microsoft YaHei");
  72. }
  73. else
  74. {
  75. paint.Typeface = SKTypeface.FromFamilyName("Segoe UI Emoji");
  76. }
  77. }
  78. // 计算字符的宽度
  79. float charWidth = paint.MeasureText(element) > maxEmojiWidth ? maxEmojiWidth : paint.MeasureText(element);
  80. textSumWidth += charWidth;
  81. // 判断当前是否超过最大宽度
  82. if (textSumWidth >= dto.MaxWidth)
  83. {
  84. // 多余的字符用省略号代替
  85. canvas.DrawText("...", x, y, paint);
  86. break;
  87. }
  88. // 绘制字符
  89. canvas.DrawText(element, x, y, paint);
  90. // 调整下一个字符的位置
  91. x += charWidth + dto.FontLeftMargin;
  92. }
  93. // 保存图像到文件
  94. using var image = SKImage.FromBitmap(bitmap);
  95. using var data = image.Encode(SKEncodedImageFormat.Png, 100);
  96. // 流不关闭,需要在外部关闭
  97. var stream = new MemoryStream();
  98. data.SaveTo(stream);
  99. // 替换为要保存的文件路径
  100. //string filePath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "yug_test.png");
  101. //using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
  102. //{
  103. // // 将 MemoryStream 中的数据写入到文件流
  104. // stream.WriteTo(fileStream);
  105. //}
  106. return stream;
  107. }
  108. /// <summary>
  109. /// 检查字符串是否包含中文
  110. /// </summary>
  111. /// <param name="text"></param>
  112. /// <returns></returns>
  113. public static bool CheckStringChineseUn(string text)
  114. {
  115. bool res = false;
  116. foreach (char t in text)
  117. {
  118. if (t >= 0x4e00 && t <= 0x9fff)
  119. {
  120. res = true;
  121. break;
  122. }
  123. }
  124. return res;
  125. }
  126. }
  127. public class UserAliasGenerateDTO
  128. {
  129. /// <summary>
  130. /// 内容区域最大宽度
  131. /// </summary>
  132. public int MaxWidth { get; set; }
  133. /// <summary>
  134. /// 图片宽度
  135. /// </summary>
  136. public int Width { get; set; }
  137. /// <summary>
  138. /// 图片宽度
  139. /// </summary>
  140. public int Height { get; set; }
  141. /// <summary>
  142. /// 内容
  143. /// </summary>
  144. public string Text { get; set; }
  145. /// <summary>
  146. /// 字体大小
  147. /// </summary>
  148. public int FontSize { get; set; }
  149. /// <summary>
  150. /// 字体颜色
  151. /// </summary>
  152. public SKColor FontColor { get; set; }
  153. /// <summary>
  154. /// 文字左边距
  155. /// </summary>
  156. public int FontLeftMargin { get; set; } = 2;
  157. }
  158. }