/// <summary> /// Generate a new captcha. /// </summary> /// <param name="cancellationToken"></param> /// <returns>The captcha.</returns> public async ValueTask <ICaptcha <Bitmap> > GenerateNewAsync(CancellationToken cancellationToken = default) { if (this.IsDisposed) { throw new ObjectDisposedException(null); } var random = RandomValueGenerator.GetRandom(); return(await Task.Run(async() => { string resultString; { var length = this.lengths[random.Next(this.lengths.Length)]; StringBuilder builder = new StringBuilder(length); for (int i = 0; i < length; i++) { builder.Append(this.characters[random.Next(this.characters.Length)]); } resultString = builder.ToString(); } Bitmap image = new Bitmap(resultString.Length * 16, 27); using Graphics g = Graphics.FromImage(image); g.Clear(Color.White); using var silverPen = new Pen(Color.Silver); for (int i = 0; i < 25; i++) { int x1 = random.Next(image.Width); int x2 = random.Next(image.Width); int y1 = random.Next(image.Height); int y2 = random.Next(image.Height); g.DrawLine(silverPen, x1, x2, y1, y2); } using LinearGradientBrush brush = new LinearGradientBrush( new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true); g.DrawString(resultString, this.fonts[random.Next(this.fonts.Length)], brush, 3, 2); for (int i = 0; i < 100; i++) { int x = random.Next(image.Width); int y = random.Next(image.Height); image.SetPixel(x, y, Color.FromArgb(random.Next())); } g.DrawRectangle(silverPen, 0, 0, image.Width - 1, image.Height - 1); var id = await this.SaveAnswerAsync(resultString, cancellationToken).ConfigureAwait(false); return new Captcha() { Display = image, Id = id }; }, cancellationToken).ConfigureAwait(false)); }