动漫人物做羞羞事的网站/上海网络推广优化公司
在前端开发的时候,常用的一个需求就是图形验证码,那么如果后端使用Delphi开发,随机生成一个验证码图片,是如何实现呢?
其实如果是VCL,就是调用TBitMap对象来实现,TBitMap有详细的Canvas操作函数,具体的操作参见Delphi的帮助文档。
直接上源代码如下:
{*******************************************************
生成验证码图片: 2023-04-07
作者:sensor(老吴)QQ:910731685
将生成的图片转换成png格式,减少传输数据量。
如果是BMP图片,样本:19KB,转换成png后大小为:3KB
*******************************************************}
unit uSZHN_VerifyCode;interface
usesSystem.Classes,System.SysUtils,VCL.Graphics,System.UIConsts,System.UITypes,Vcl.ExtCtrls,
// Vcl.Imaging.jpeg,Vcl.Imaging.pngimage,System.Types;type// 生成验证码组件TSZHN_GenerateVerifyCode = classprivate const// 定义字典表,不要零(0),因为零和字母O样子太接近arrStr: array [0 .. 42] of char = ('1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','我','爱','中','国','科','技','畅','想');privateFBitmapWidth: integer; // 图片宽度FBitmapHeight: integer; // 图片高度FCodeCount: integer; // 取验证码字符的个数,默认是4个字符FFontName: string; // 字体名称FMinFontSize: integer; // 最小字体大小FRandomLineCount: integer; // 背景随机线条数FXRandomLen: integer; // X的随机值长度FYRandomLen: integer; // Y的随机值长度// 画出验证码函数function VerifyCodeDrawImg(BMP : TBitmap): string;publicconstructor Create;procedure GetVerifyCodeAndImage(ImageStream: TStream; var VerifyCode: string);publishedproperty Width: integer read FBitmapWidth write FBitmapWidth;property Height: integer read FBitmapHeight write FBitmapHeight;property CodeCount: integer read FCodeCount write FCodeCount;property MinFontSize: integer read FMinFontSize write FMinFontSize;property RandomLineCount: integer read FRandomLineCount write FRandomLineCount;property XRandomLen: integer read FXRandomLen write FXRandomLen;property YRandomLen: integer read FYRandomLen write FYRandomLen;end;//外部调用函数, ImageStream 参数返回的是生成的验证码图片数据流,结果为验证码字符串
function Create_VerifyCode(ImageStream: TStream): string;implementation//外部调用函数, ImageStream 参数返回的是生成的验证码图片数据流,结果为验证码字符串
function Create_VerifyCode(ImageStream: TStream): string;
varSZHN_GenerateVerifyCode : TSZHN_GenerateVerifyCode;
beginSZHN_GenerateVerifyCode := TSZHN_GenerateVerifyCode.Create;trySZHN_GenerateVerifyCode.GetVerifyCodeAndImage(ImageStream, Result);finallySZHN_GenerateVerifyCode.Free;end;end;constructor TSZHN_GenerateVerifyCode.Create();
begininherited;FBitmapWidth := 120;FBitmapHeight := 40;FCodeCount := 4;FMinFontSize := 4;FRandomLineCount := 10;FXRandomLen := 5;FYRandomLen := 4;
end;// 获取验证码和图片的流数据
procedure TSZHN_GenerateVerifyCode.GetVerifyCodeAndImage(ImageStream: TStream;var VerifyCode: string);
varBMP : TBitmap;PNG : TPNGImage;
beginBMP := TBitmap.Create;PNG := TPNGImage.Create;try// 默认 宽120,高40BMP.Width := FBitmapWidth;BMP.Height:= FBitmapHeight;//画验证码图,返回的是图形字符串VerifyCode := VerifyCodeDrawImg(BMP);//转换成png格式PNG.Assign(BMP);PNG.CompressionLevel := 9; //最高压缩率 0..9PNG.SaveToStream(ImageStream); //保存成 Stream ,以便可以传递给前端(Base64)finallyFreeAndNil(BMP);FreeAndNil(PNG);end;end;// 画出验证码函数
function TSZHN_GenerateVerifyCode.VerifyCodeDrawImg(BMP : TBitmap): string;
varI, j, k: integer;X, Y, W, H: integer;vLeft: integer;strResult: string;//随机颜色函数function RandomColor : TColor;beginResult := Random($FF) shl 16 + Random($FF) shl 8 + Random($FF);end;//随机生成字体名字,内置6种字体随机切换function Random_FontName: string;varFontNames : Tarray<string>;beginSetLength(FontNames,6);FontNames[0] := 'Microsoft JhengHei UI';FontNames[1] := '宋体';FontNames[2] := 'Microsoft YaHei UI';FontNames[3] := 'Ink Free';FontNames[4] := 'Malgun Gothic';FontNames[5] := 'Cascadia Code';Randomize;Result := FontNames[Random(1000000) mod 6];end;begin// 随机获取字符,默认4个字符For j := 1 to FCodeCount dobeginRandomize;k := Random(1000000) mod 43;strResult := strResult + trim(arrStr[k]);end;vLeft := 5;//设置背景颜色BMP.Canvas.Brush.Style := bsSolid;BMP.Canvas.Brush.Color := RandomColor;BMP.Canvas.FillRect(TRect.Create(0, 0, FBitmapWidth, FBitmapHeight));// 随机画10条线for j := 1 to FRandomLineCount dobeginRandomize;BMP.Canvas.Brush.Style := bsCross;BMP.Canvas.Pen.Color := RandomColor;BMP.Canvas.Pen.Width := 1;BMP.Canvas.Pen.Mode := pmXor;BMP.Canvas.MoveTo(Random(FBitmapWidth), Random(FBitmapHeight));BMP.Canvas.LineTo(Random(FBitmapWidth), Random(FBitmapHeight));end;for I := 1 to length(strResult) dobeginRandomize;// 随机字体颜色,这里暂时不用每个字符一个随机颜色BMP.Canvas.Font.Color := RandomColor;//设置字体名字BMP.Canvas.Font.Name := Random_FontName;// 字体大小BMP.Canvas.Font.Size := Random(8) + FMinFontSize;if BMP.Canvas.Font.Size < (FMinFontSize + 5) thenBMP.Canvas.Font.Size := BMP.Canvas.Font.Size + 5;if Random(2) = 1 thenBMP.Canvas.Font.Style := [TFontStyle.fsBold]elseBMP.Canvas.Font.Style := [TFontStyle.fsItalic];beginX := Random(FXRandomLen) + vLeft;Y := Random(FYRandomLen);W := BMP.Canvas.TextWidth(strResult[I]);H := BMP.Canvas.TextHeight(strResult[I]);BMP.Canvas.TextOut(X,Y,strResult[I]);vLeft := X + W + 1;end;end;Result := strResult; // 返回值 ,验证码字符串
end;end.
具体使用代码:
usesuSZHN_VerifyCode;
varsVerifyCode : string; //验证码字符串TM : TMemoryStream; //验证码图片数据流信息
beginTM := TMemoryStream.Create;sVerifyCode := Create_VerifyCode(TM);TM.SaveToFile('C:\Temp\1.png'); //可以保存成文件Image1.Picture.LoadFromFile('C:\Temp\1.png'); //可以直接在Image1中显示出来TM.Free;
end;