From the initial sliding verification code to the realization of rotating verification code! Not only practiced the use of SkiaSharp, but also learned a lot. I saw a splicing verification code function on the Internet, and my hands were itchy. Combining the two verification codes implemented earlier, let's learn how to realize the splicing verification code function!
Table of contents
Effect preview
Realization principle
In fact, splicing verification codes is much simpler to implement than sliding verification codes and selecting verification codes, because splicing verification codes does not involve grooves and slider templates. All you need is a background image!
Get the picture : Get the background picture first. Convert background image to SKBitmap
.
Get a random value : According to the width and height of the picture, set a fixed X-coordinate spacing spacingX
and a Y-coordinate spacing spacingY
, and then define a random value of X-coordinate randomX
and Y-coordinate random value to randomY
cut the image horizontally : according to the obtained random value randomY
, horizontally Cut the background image into 2 pieces to make it into two parts, top and bottom.
Cut the picture vertically : According to the obtained random value randomX
, cut the upper half into two pieces vertically!
In this way, we get 4 pictures.
Make the upper half left and right two pictures. Replace the position to form a new picture
Combine the new picture with the lower part to form a picture.
In this way, we have completed the picture of stitching the verification code. Pass him to the front.
The front end positions the slider to the upper half according to the data passed by the server. Then control the movement of the upper part of the picture to achieve the effect of splicing the verification code!
code part
The part of getting the background image has been mentioned earlier.
You can refer to: NET 6 realizes the generation of sliding verification code (6), verification code background image, slider image and groove image
Get background image
//拼接验证码没有模板,只需要背景图
//获取背景图
var background = await _resourceManager.RandomBackground();
Convert the background image toSKBitmap
using var backgroundImage = SKBitmap.Decode(background);
Calculation interval
//X坐标间距
int spacingX = backgroundImage.Width / 8;
//Y坐标间距
int spacingY = backgroundImage.Height / 4;
The interval is defined mainly to generate random values for the X and Y axes.
define random value
int randomX = _random.Next(spacingX, backgroundImage.Width - backgroundImage.Width /5);
int randomY = _random.Next(spacingY, backgroundImage.Height - spacingY);
Define X-axis random value randomX
and Y-axis random value randomY
.
**randomY**: The main function of randomY is to randomly cut the background image into upper and lower parts.
**randomX **The main function is to randomly cut the background image into left and right parts.
Cut the background image into upper and lower parts
First define a method, the function of this method is to cut the specified picture into two parts according to the incoming content.
public static List<byte[]> SplitImage(int pos,bool direction,SKBitmap img)
{
int StartImageWidth,
StartImageHeight,
EndImageWidth,
EndImageHeight;
int EndScanX, EndScanY;
int ImageWidth = img.Width;
int ImageHeight = img.Height;
StartImageWidth = direction ? ImageWidth : pos;
StartImageHeight = direction ? ImageHeight - pos : ImageHeight;
EndImageWidth = direction ? ImageWidth : ImageWidth - StartImageWidth;
EndImageHeight = direction ? pos : ImageHeight;
EndScanX = direction ? 0 : pos;
EndScanY = direction ? StartImageHeight : 0;
using var StartImage = new SKBitmap(StartImageWidth, StartImageHeight);
using var StartCanvas = new SKCanvas(StartImage);
SKRect StartSourceRect = new SKRect(0, 0, StartImageWidth, StartImageHeight);
SKRect StartDestRect = new SKRect(0, 0, StartImageWidth, StartImageHeight);
StartCanvas.DrawBitmap(img, StartSourceRect, StartDestRect);
using var EndImage = new SKBitmap(EndImageWidth, EndImageHeight);
using var EndCanvas = new SKCanvas(EndImage);
SKRect EndSourceRect = new SKRect(EndScanX, EndScanY, EndScanX + EndImageWidth, EndScanY + EndImageHeight);
SKRect EndDestRect = new SKRect(0, 0, EndImageWidth, EndImageHeight);
EndCanvas.DrawBitmap(img, EndSourceRect, EndDestRect);
List<byte[]> result = new List<byte[]>();
using var StartImg = SKImage.FromBitmap(StartImage);
using var StartData = StartImg.Encode(SKEncodedImageFormat.Png, 100);
using var EndImg = SKImage.FromBitmap(EndImage);
using var EndData = EndImg.Encode(SKEncodedImageFormat.Png, 100);
result.Add(StartData.ToArray());
result.Add(EndData.ToArray());
return result;
}
The SplitImage method has 3 parameters:
pos : Split point, which refers to where to start cutting on the image.
direction : cutting direction. true for the horizontal direction, false for the vertical direction!
img : the image to be cut.
int StartImageWidth,
StartImageHeight,
EndImageWidth,
EndImageHeight;
int EndScanX, EndScanY;
int ImageWidth = img.Width;
int ImageHeight = img.Height;
Because the picture is to be cut into 2 pictures, it StartImageWidth
means StartImageHeight
the width and height of the first picture. EndImageWidth
and EndImageHeight
represent the width and height of the second image.
EndScanX
Indicates the cutting point of the X coordinate, and EndScanY
represents the cutting point of the Y coordinate.
Next, define two respectively SKCanvas
, StartCanvas
and EndCanvas
. Represents the canvas of the first image and the canvas of the second image. After defining, define two more SKRect
. SKRect
Represents a rectangle, he has 4 parameters. left
are , top
, right
and , respectively bottom
. I just saw these 4 parameters a bit confused, what does this mean? Immediately reacted. where lert
and top
determine the coordinates of the upper left corner. right
and bottom
determine the coordinates of the lower right corner. Then use DrawBitmap
the method to get two pictures.
It should be noted that what is returned is a List<byte[]>. The data of two pictures are saved in it byte[]
. Why not return the List directly? because it is used in the code using var
. If List is returned. With this method, the SKBitmaps of the two images are released. Then use the SKBitmap of these two pictures again, it will be abnormal. If it is used var
, it is not easy to find a suitable time to release them. So a List<byte[]> is returned. There is no delay in this way.
With this method, we can cut the picture into two required pictures according to the requirements.
Cut the picture into upper and lower parts:
List<byte[]> bgImageList = CaptchaImageUtils.SplitImage(randomY, true, backgroundImage);
using var bgImage0 = SKBitmap.Decode(bgImageList[0]);
using var bgImage1 = SKBitmap.Decode(bgImageList[1]);
Cut the upper half of the image into left and right parts
List<byte[]> bgImageTopList = CaptchaImageUtils.SplitImage(randomX, false, bgImage0);
using var bgImageTop0 = SKBitmap.Decode(bgImageTopList[0]);
using var bgImageTop1 = SKBitmap.Decode(bgImageTopList[1]);
The method of use SplitImage
is to cut the upper half of the upper and lower parts in the figure that has just been cut into two left and right parts. At this point, we have 4 images!
Stitch pictures
Our plan is to stitch bgImageTop0
together bgImageTop1
, but the order of stitching is bgImageTop1+bgImageTop0. In this way, a picture like this is obtained, we call it SliderImage
and then splicing SliderImage
with bgImage1
and is completed.
Let's take a look at the splicing method first, give this splicing method a name, let's call ConcatImage
it. The specific code is:
public static byte[] ConcatImage(bool direction,int width,int height, params SKBitmap[] imgArr)
{
int pos = 0;
using var NewImage = new SKBitmap(width, height);
using var NewImageCanvas = new SKCanvas(NewImage);
foreach(var img in imgArr)
{
float x = direction ? pos : 0;
float y = direction ? 0 : pos;
NewImageCanvas.DrawBitmap(img, x,y);
pos += direction ? img.Width : img.Height;
}
using var NewImg = SKImage.FromBitmap(NewImage);
using var NewData = NewImg.Encode(SKEncodedImageFormat.Png, 100);
return NewData.ToArray();
}
ConcatImage
The method has 4 parameters,
direction : bool
type, indicating the splicing direction, true for horizontal splicing, false for vertical splicing.
width : int
type, the width of the spliced image
height : int
type, the height of the spliced image
imgArr : params
type, the array of the spliced image
Define SKBitmap
and respectively SKCanvas
. Then loop through the array. Stitch the pictures together and finally return one byte[]
.
After stitching is complete, return the picture to the front end.
return new ConcatImageCaptchaInfo
{
BackgroundImage = bgImage.ToBase64String(SKEncodedImageFormat.Png),
SliderImage = null,
BackgroundImageWidth = bgImage.Width,
BackgroundImageHeight = bgImage.Height,
SliderImageWidth = 0,
SliderImageHeight = 0,
RandomX = randomX,
RandomY = randomY,
Tolerant = 0.05F,
CaptchaType = CaptchaTypeConstant.CONCAT
};
ToBase64String
Extension methods written for myself. You can refer to .Net 6 to implement the rotation verification code . This article has written this method.
The front-end code is basically the same as the previous sliding verification code. Just change it a little bit!
Summarize
There are other types of verification codes, such as click verification codes, graphic verification codes, etc. Will gradually improve.
Click on the official account card below to follow me! Learn together and progress together!