diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs index 5fec9e7cdb..71b0aee458 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs @@ -1,19 +1,17 @@ using System; -using SixLabors.Fonts; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats; +using ImageMagick; namespace Volo.CmsKit.Public.Web.Security.Captcha; public class CaptchaOptions { - public Color[] TextColor { get; set; } = new Color[] + public MagickColor[] TextColor { get; set; } = new MagickColor[] { - Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green + MagickColors.Blue, MagickColors.Black, MagickColors.Black, MagickColors.Brown, MagickColors.Gray, MagickColors.Green }; - public Color[] DrawLinesColor { get; set; } = new Color[] + public MagickColor[] DrawLinesColor { get; set; } = new MagickColor[] { - Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green + MagickColors.Blue, MagickColors.Black, MagickColors.Black, MagickColors.Brown, MagickColors.Gray, MagickColors.Green }; public float MinLineThickness { get; set; } = 0.7f; @@ -26,15 +24,15 @@ public class CaptchaOptions public ushort NoiseRate { get; set; } = 500; - public Color[] NoiseRateColor { get; set; } = new Color[] { Color.Gray }; + public MagickColor[] NoiseRateColor { get; set; } = new MagickColor[] { MagickColors.Gray }; public byte FontSize { get; set; } = 32; - public FontStyle FontStyle { get; set; } = FontStyle.Regular; + public FontStyleType FontStyle { get; set; } = FontStyleType.Normal; public EncoderTypes EncoderType { get; set; } = EncoderTypes.Png; - public IImageEncoder Encoder => RandomTextGenerator.GetEncoder(EncoderType); + public MagickFormat Encoder => RandomTextGenerator.GetEncoder(EncoderType); public byte DrawLines { get; set; } = 2; diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs index df5818f88c..40f94e4073 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs @@ -1,21 +1,19 @@ using System; using System.Security.Cryptography; using System.Text; -using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; +using ImageMagick; namespace Volo.CmsKit.Public.Web.Security.Captcha; public static class RandomTextGenerator { private static readonly char[] AllowedChars = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVXYZW23456789".ToCharArray(); - public static IImageEncoder GetEncoder(EncoderTypes encoderType) + public static MagickFormat GetEncoder(EncoderTypes encoderType) { - IImageEncoder encoder = encoderType switch + var encoder = encoderType switch { - EncoderTypes.Png => new PngEncoder(), - EncoderTypes.Jpeg => new JpegEncoder(), + EncoderTypes.Png => MagickFormat.Png, + EncoderTypes.Jpeg => MagickFormat.Jpeg, _ => throw new ArgumentException($"Encoder '{encoderType}' not found!") }; diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs index f8f1c3d071..00d522b509 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs @@ -1,21 +1,13 @@ using System; -using System.IO; using System.Linq; -using System.Numerics; using System.Threading.Tasks; -using SixLabors.Fonts; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using Volo.Abp; using Volo.CmsKit.Localization; using Microsoft.Extensions.Localization; using Volo.Abp.DependencyInjection; -using Color = SixLabors.ImageSharp.Color; -using PointF = SixLabors.ImageSharp.PointF; using Volo.Abp.Caching; using Microsoft.Extensions.Caching.Distributed; +using ImageMagick; namespace Volo.CmsKit.Public.Web.Security.Captcha; @@ -108,93 +100,79 @@ public class SimpleMathsCaptchaGenerator : ITransientDependency private byte[] GenerateInternal(string stringText, CaptchaOptions options) { - byte[] result; + var random = new Random(); + var fontName = MagickNET.FontFamilies.First(); + + var drawables = new Drawables() + .Font(fontName, options.FontStyle, FontWeight.Normal, FontStretch.Normal) + .FontPointSize(options.FontSize) + .StrokeColor(MagickColors.Transparent); + + var size = (ushort)(drawables.FontTypeMetrics(stringText)?.TextWidth ?? 0); + using var image = new MagickImage(MagickColors.White, size + 15, options.Height); - using (var image = new Image(options.Width, options.Height)) + double position = 0; + var startWith = (byte)random.Next(5, 10); + + foreach (var character in stringText) { - float position = 0; - var random = new Random(); - var startWith = (byte)random.Next(5, 10); - image.Mutate(ctx => ctx.BackgroundColor(Color.Transparent)); - - var fontFamily = SystemFonts.Families - .FirstOrDefault(x => x.GetAvailableStyles().Contains(options.FontStyle), SystemFonts.Families.First()) - .Name; - - var font = SystemFonts.CreateFont(fontFamily, options.FontSize, options.FontStyle); - - foreach (var character in stringText) - { - var text = character.ToString(); - var color = options.TextColor[random.Next(0, options.TextColor.Length)]; - var location = new PointF(startWith + position, random.Next(6, 13)); - image.Mutate(ctx => ctx.DrawText(text, font, color, location)); - position += TextMeasurer.MeasureSize(character.ToString(), new TextOptions (font) - { - Origin = location - }).Width; - } + var text = character.ToString(); + var color = options.TextColor[random.Next(0, options.TextColor.Length)]; + drawables.FillColor(new MagickColor(color.R, color.G, color.B, color.A)) + .Text(startWith + position, + RandomTextGenerator.GenerateNextFloat(image.BaseHeight / 2.3, image.BaseHeight / 1.7), text); - //add rotation - var rotation = GetRotation(options); - image.Mutate(ctx => ctx.Transform(rotation)); + position += drawables.FontTypeMetrics(text)?.TextWidth ?? 0; + } + + // add rotation + var rotation = GetRotation(options); + drawables.Rotation(rotation); - // add the dynamic image to original image - var size = (ushort)TextMeasurer.MeasureSize(stringText, new TextOptions(font)).Width; - var img = new Image(size + 15, options.Height); - img.Mutate(ctx => ctx.BackgroundColor(Color.White)); + drawables.Draw(image); - Parallel.For(0, options.DrawLines, i => + Parallel.For(0, options.DrawLines, _ => + { + // ReSharper disable once AccessToDisposedClosure + if (image is { IsDisposed: false }) { var x0 = random.Next(0, random.Next(0, 30)); - var y0 = random.Next(10, img.Height); + var y0 = random.Next(10, image.Height); - var x1 = random.Next(30, img.Width); - var y1 = random.Next(0, img.Height); + var x1 = random.Next(30, image.Width); + var y1 = random.Next(0, image.Height); - img.Mutate(ctx => - ctx.DrawLine(options.TextColor[random.Next(0, options.TextColor.Length)], - RandomTextGenerator.GenerateNextFloat(options.MinLineThickness, options.MaxLineThickness), - new PointF[] { new PointF(x0, y0), new PointF(x1, y1) }) - ); - }); - - img.Mutate(ctx => ctx.DrawImage(image, 0.80f)); + image.Draw(new Drawables() + .StrokeColor(options.DrawLinesColor[random.Next(0, options.DrawLinesColor.Length)]) + .StrokeWidth(RandomTextGenerator.GenerateNextFloat(options.MinLineThickness, + options.MaxLineThickness)) + .Line(x0, y0, x1, y1)); + } + }); - Parallel.For(0, options.NoiseRate, _ => + Parallel.For(0, options.NoiseRate, _ => + { + if (image is { IsDisposed: false }) { - var x0 = random.Next(0, img.Width - 1); - var y0 = random.Next(0, img.Height - 1); - img.Mutate( - ctx => ctx - .DrawLine(options.NoiseRateColor[random.Next(0, options.NoiseRateColor.Length)], - RandomTextGenerator.GenerateNextFloat(0.5, 1.5), - new PointF[] { new Vector2(x0, y0), new Vector2(x0 + 0.005f, y0 + 0.005f) }) + var x = random.Next(0, image.Width); + var y = random.Next(0, image.Height); + image.Draw(new Drawables() + .FillColor(options.NoiseRateColor[random.Next(0, options.NoiseRateColor.Length)]) + .Point(x, y) ); - }); - - img.Mutate(x => - { - x.Resize(options.Width, options.Height); - }); - - using (var ms = new MemoryStream()) - { - img.Save(ms, options.Encoder); - result = ms.ToArray(); } - } + }); - return result; + image.Resize(new MagickGeometry(options.Width, options.Height) { IgnoreAspectRatio = true }); + + return image.ToByteArray(options.Encoder); } - private static AffineTransformBuilder GetRotation(CaptchaOptions options) + private double GetRotation(CaptchaOptions options) { var random = new Random(); - var width = random.Next(10, options.Width); - var height = random.Next(10, options.Height); - var pointF = new PointF(width, height); var rotationDegrees = random.Next(0, options.MaxRotationDegrees); - return new AffineTransformBuilder().PrependRotationDegrees(rotationDegrees, pointF); + return rotationDegrees; } + } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj index 81177e2462..165eae38c9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj @@ -18,8 +18,7 @@ - - +