public override async ValueTask <CaptchaImage> CaptchaCreate(BaseCaptchaOptions options) { var path = _imageProvider.SliderRoot; using Image <Rgba32> image = await _imageProvider.LoadBackground(); using var alpha = await _imageProvider.LoadAlpha(path); using var border = await _imageProvider.LoadBorder(path); using var slider = await _imageProvider.LoadSlider(path); var fullImage = image.Clone(); var option = options ?? _options; int col = option.Col; int row = option.Row; int rotate = rd.Next(0, 2); var point = RandPoint(image, alpha); _driver.CopyNoAlpha(image, new Point(point.X, point.Y), alpha); alpha.Mutate(x => { x.DrawImage(border, 1); if (rotate > 0) { rotate = rd.Next(0, 2); x.RotateFlip(RotateMode.Rotate180, rotate == 1?FlipMode.Horizontal:FlipMode.Vertical); rotate = rotate == 0 ? 180 : -180; } }); image.Mutate(x => { x.DrawImage(slider, new Point(point.X, point.Y), 1); if (option?.Safelevel != SafelevelEnum.None) { var level = (int)option.Safelevel + 1; for (int i = 0; i < level; i++) { using var safe = slider.Clone(); var rePoint = RandPoint(image, slider); if ((i & 1) == 1) { rePoint.Y = point.Y; } var xpos = Math.Abs(point.X - rePoint.X); var ypost = Math.Abs(point.Y - rePoint.Y); if (xpos <= (slider.Width >> 1)) { xpos = rd.Next(slider.Width - xpos, slider.Width); rePoint.X += (i & 1) == 1 ? -xpos : xpos; } if (ypost <= (slider.Height >> 1)) { ypost = rd.Next(0, slider.Height >> 1); rePoint.Y += (i & 1) == 1 ? ypost : -ypost; } safe.Mutate(x => x.Rotate(rd.Next(30, 60))); x.DrawImage(safe, rePoint.Point, 0.7f); } } }); var randData = _driver.RandImagesBy(image, ref col, ref row); _captchaImageBuilder.AddBackground(fullImage) .AddGap(alpha.Clone()) .AddRandData(randData) .AddGapBackground(_driver.ImageByRandImages(image, randData, col)) .AddIndex(randData.Select(x => x.Index).ToArray()) .AddChange(randData.Where(x => x.Change).Select(x => x.Index).ToArray()) .AddColumn(col).AddRow(row) .AddType(Type).AddName(Name) .AddTips("向右拖动滑块填充拼图") .AddPoints(new List <CaptchaPoint>(1) { point }) .AddExtension(new SliderExtension(point.Y, rotate)) .AddOptions(option); return(_captchaImageBuilder.Build()); }
public override async ValueTask <CaptchaImage> CaptchaCreate(BaseCaptchaOptions options = null) { var path = _imageProvider.SliderRoot; using Image <Rgba32> image = await _imageProvider.LoadBackground(); var fullImage = image.Clone(); var option = options ?? _options; int col = option.Col; int row = option.Row; var lumps = await _imageProvider.LoadRandImages(_imageProvider.LumpRoot); var count = Math.Min((int)option.Safelevel + 1, lumps.Count); var points = new List <CaptchaPoint>(lumps.Count); var rdPoints = RandPoints(image, lumps.ToArray()); image.Mutate(x => { foreach (var lump in lumps) { var point = RandPoint(rdPoints); if (point != null) { x.DrawImage(lump, new Point(point.X, point.Y), 1); points.Add(point); } } }); rdPoints.Clear(); var randData = _driver.RandImagesBy(image, ref col, ref row); var randImage = _driver.ImageByRandImages(image, randData, col); var xpos = 0; var ypos = randImage.Height + 2; var height = lumps.Max(x => x.Height) + 2; var pointRandImage = new Image <Rgba32>(randImage.Width, randImage.Height + height); _driver.Copy(randImage.CloneAs <Rgba32>(), Point.Empty, pointRandImage); pointRandImage.Mutate(x => { for (int i = 0; i < lumps.Count; i++) { using var lump = lumps[i].Clone(); lump.Mutate(x => x.Invert()); x.DrawImage(lump, new Point(xpos, ypos), 1); xpos += lump.Width + 5; lumps[i].Dispose(); } }); _captchaImageBuilder.AddBackground(fullImage) .AddRandData(randData) .AddGapBackground(pointRandImage) .AddIndex(randData.Select(x => x.Index).ToArray()) .AddChange(randData.Where(x => x.Change).Select(x => x.Index).ToArray()) .AddColumn(col).AddRow(row) .AddType(Type).AddName(Name) .AddTips("请依次点击") .AddExtension(new PointExtension(height, xpos)) .AddPoints(points).AddOptions(option); return(_captchaImageBuilder.Build()); }