CapchaGenerator.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace CapchaLibrary
  9. {
  10. public class CapchaGenerator
  11. {
  12. /// <summary>
  13. /// Базовый конструктор, создающий генератор капчи по умолчанию
  14. /// </summary>
  15. public CapchaGenerator()
  16. {
  17. ValidCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  18. SymbolsCount = 6;
  19. NoiseCount = 25;
  20. random = new Random(DateTime.Now.Microsecond);
  21. }
  22. /// <summary>
  23. /// Конструктор генератора, позволяющий задавать используемые при создании капчи символы, количество символов в капче и количество шума
  24. /// </summary>
  25. /// <param name="validCharacters">Используемые при создании символы</param>
  26. /// <param name="symbolsCount">Количество символов в капче</param>
  27. public CapchaGenerator(string validCharacters, int symbolsCount, int noiseCount)
  28. {
  29. ValidCharacters = validCharacters;
  30. SymbolsCount = symbolsCount;
  31. NoiseCount = noiseCount;
  32. random = new Random(DateTime.Now.Microsecond);
  33. }
  34. /// <summary>
  35. /// Строка состоящая из символов, использующихся при создании капчи
  36. /// </summary>
  37. public string ValidCharacters { get; init; }
  38. /// <summary>
  39. /// Количество символов в капче
  40. /// </summary>
  41. public int SymbolsCount { get; init; }
  42. /// <summary>
  43. /// Количество шума на капче
  44. /// </summary>
  45. public int NoiseCount { get; init; }
  46. /// <summary>
  47. /// Метод генерации капчи
  48. /// </summary>
  49. /// <returns>Данные по сгенерированной капче</returns>
  50. public CapchaData GenerateCapcha()
  51. {
  52. string capchaCode = GenerateCapchaCode();
  53. Bitmap capcha = GenerateCapcha(capchaCode);
  54. return new CapchaData(capcha, capchaCode);
  55. }
  56. private readonly Dictionary<int,(Color, Brush)> CapchaColors = new Dictionary<int,(Color, Brush)>()
  57. {
  58. { 0, (Color.Aquamarine, Brushes.Aqua) },
  59. { 1, (Color.PapayaWhip, Brushes.Pink) },
  60. { 2, (Color.Coral, Brushes.IndianRed) },
  61. };
  62. private readonly Random random;
  63. /// <summary>
  64. /// Метод генерации кода капчи
  65. /// </summary>
  66. /// <returns>Код капчи</returns>
  67. private string GenerateCapchaCode() =>
  68. new string(Enumerable.Repeat(ValidCharacters, SymbolsCount)
  69. .Select(s => s[random.Next(s.Length)])
  70. .ToArray());
  71. /// <summary>
  72. /// Метод генерации изображения капчи
  73. /// </summary>
  74. /// <param name="capchaCode">Код капчи</param>
  75. /// <returns>Изображение капчи</returns>
  76. private Bitmap GenerateCapcha(string capchaCode)
  77. {
  78. Bitmap capcha = new(2560, 1440);
  79. (Color, Brush) colors = GetRandomCapchaColor();
  80. using (Graphics graphics = Graphics.FromImage(capcha))
  81. {
  82. graphics.Clear(colors.Item1);
  83. int SymbolX = 150;
  84. int SymbolY = 650;
  85. foreach (char symbol in capchaCode)
  86. {
  87. int NextSymbolY = SymbolY + (random.Next(0, 600) - 600);
  88. graphics.DrawString(symbol.ToString(), new Font("Comic Sans MS", 320, FontStyle.Bold), colors.Item2, new PointF(SymbolX, NextSymbolY));
  89. SymbolX += 360;
  90. }
  91. for(int noiseCounter = 0; noiseCounter < NoiseCount; noiseCounter++)
  92. {
  93. graphics.DrawLine(new Pen(Brushes.DarkBlue, 5)
  94. , new Point(random.Next(0, 2560), random.Next(0, 1440))
  95. , new Point(random.Next(0, 2560), random.Next(0, 1440)));
  96. }
  97. }
  98. return capcha;
  99. }
  100. private (Color, Brush) GetRandomCapchaColor()
  101. {
  102. (Color, Brush) brush;
  103. CapchaColors.TryGetValue(random.Next(0,3), out brush);
  104. return brush;
  105. }
  106. }
  107. }