生成验证码的方式有很多种,如下则是比较简单的实现,且运用了正余弦曲线来扭曲验证码字符。

unit AuthenticodeGenerate;

interface

uses
SysUtils, Windows, ExtCtrls, Graphics; function GenerateAuthenticode(const Img: TImage; const Len: Integer = 4): string; implementation const
cCharDigitArrayLen = 6;
cCharDigitArray : array[0..cCharDigitArrayLen - 1] of Char = ('3', '4', '5', '6', '7', '8'); cCharLowerLetterArrayLen = 13;
cCharLowerLetterArray: array[0..cCharLowerLetterArrayLen - 1] of Char = ('b', 'c', 'e', 'h', 'j', 'k', 'm', 'n', 's', 't', 'v', 'w', 'y'); cCharUpperLetterArrayLen = 19;
cCharUpperLetterArray: array[0..cCharUpperLetterArrayLen - 1] of Char = ('A', 'B', 'C', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'V', 'W', 'Y'); cArrayTypeNum = 3; cFontNameNum = 5;
cFontNameArray: array[0..cFontNameNum - 1] of string = ('Arial', 'Tahoma', '宋体', '幼圆', '微软雅黑'); function TwistImage(const SrcBmp: TBitmap; XDir: Boolean; MultFactor: Double; Phase: Double; SinTrick: Boolean): TBitmap;
const
cTwicePi = 6.283185;
var
BaseAxisLen : Double;
I, J : Integer;
DestX, DestY: Double;
OldX, OldY : Integer;
Color : TColor;
begin
Result := TBitmap.Create;
Result.SetSize(SrcBmp.Width, SrcBmp.Height); if XDir then
BaseAxisLen := Result.Height
else
BaseAxisLen := Result.Width; for I := 0 to Result.Width - 1 do
begin
for J := 0 to Result.Height - 1 do
begin
if XDir then
DestX := (cTwicePi * J) / BaseAxisLen
else
DestX := (cTwicePi * I) / BaseAxisLen; if SinTrick then
begin
DestX := DestX + Phase;
DestY := Sin(DestX);
end else
begin
DestX := DestX + Phase;
DestY := Cos(DestX);
end; if XDir then
begin
OldX := I + Round(DestY * MultFactor);
OldY := J;
end else
begin
OldX := I;
OldY := J + Round(DestY * MultFactor);
end; Color := SrcBmp.Canvas.Pixels[I, J];
if (OldX >= 0) and (OldX < Result.Width) and (OldY >= 0) and (OldY < Result.Height) then
Result.Canvas.Pixels[OldX, OldY] := Color;
end;
end;
end; procedure NoiseImage(const Img: TImage);
const
cNoiseLineNum = 5;
cNoisePointNum = 50;
var
I: Integer;
X: Integer;
Y: Integer;
begin
for I := 0 to cNoiseLineNum - 1 do
begin
Img.Canvas.Pen.Style := psSolid; case Random(3) of
0: Img.Canvas.Pen.Color := clBlack;
1: Img.Canvas.Pen.Color := clGray;
else
Img.Canvas.Pen.Color := clSilver;
end; X := Random(Img.Width);
Y := Random(Img.Height);
Img.Canvas.MoveTo(X, Y);
Img.Canvas.LineTo(X + Random(Img.Width - X), Y + Random(Img.Height - Y));
end; for I := 0 to cNoisePointNum - 1 do
begin
case Random(3) of
0: Img.Canvas.Pixels[Random(Img.Width), Random(Img.Height)] := clBlack;
1: Img.Canvas.Pixels[Random(Img.Width), Random(Img.Height)] := clGray;
else
Img.Canvas.Pixels[Random(Img.Width), Random(Img.Height)] := clSilver;
end;
end;
end; function GenerateCharacterAuthenticode(const Img: TImage; const Len: Integer = 4): string;
var
I: Integer;
V: Char;
X: Integer;
Y: Integer;
L: Integer;
begin
Result := ''; for I := 0 to Len - 1 do
begin
case Random(cArrayTypeNum) of
0:
begin
V := cCharDigitArray[Random(cCharDigitArrayLen)];
Result := Result + V;
end;
1:
begin
V := cCharLowerLetterArray[Random(cCharLowerLetterArrayLen)];
Result := Result + V;
end;
else
begin
V := cCharUpperLetterArray[Random(cCharUpperLetterArrayLen)];
Result := Result + V;
end;
end;
end; L := 2 + Random(2);
Img.Picture := nil; for I := 0 to Length(Result) - 1 do
begin
Img.Canvas.Font.Size := Random(5) + 17;
Img.Canvas.Font.Color := RGB(Random(256) and $C0, Random(256) and $C0, Random(256) and $C0);
case Random(3) of
0: Img.Canvas.Font.Style := [fsBold];
1: Img.Canvas.Font.Style := [fsItalic];
end;
Img.Canvas.Font.Name := cFontNameArray[Random(cFontNameNum)];
X := Random(4) + L;
Y := Random(2) + 4;
Img.Canvas.TextOut(X, Y, Result[I + 1]);
L := X + Img.Canvas.TextWidth(Result[I + 1]) + Random(2);
end; if Random(2) = 0 then
begin
if Random(2) = 0 then
Img.Picture.Bitmap := TwistImage(Img.Picture.Bitmap, True, 8 + Random(3), 1 + Random(2), True)
else
Img.Picture.Bitmap := TwistImage(Img.Picture.Bitmap, False, 8 + Random(3), 1 + Random(2), True);
end else
begin
if Random(2) = 0 then
Img.Picture.Bitmap := TwistImage(Img.Picture.Bitmap, True, 8 + Random(3), 1 + Random(2), False)
else
Img.Picture.Bitmap := TwistImage(Img.Picture.Bitmap, False, 8 + Random(3), 1 + Random(2), False);
end; NoiseImage(Img);
end; function GenerateAuthenticode(const Img: TImage; const Len: Integer): string;
begin
Result := GenerateCharacterAuthenticode(Img, Len);
end; initialization
Randomize; end.

调用很简单:

uses
AuthenticodeGenerate; procedure TfrmMain.btnTestClick(Sender: TObject);
begin
lbl1.Caption := GenerateAuthenticode(img1);
end;

于是就有:

注:

1)、为减少识别难度,去掉了几个不易识别的字符如 1、I 等;

2)、验证码背景色当然也可以(应该)随机。

http://www.cnblogs.com/ecofast/p/4224016.html

验证码生成器(在TImage.Canvas上写字,很好看)的更多相关文章

  1. 【自己给自己题目做】:如何在Canvas上实现魔方效果

    最终demo -> 3d魔方 体验方法: 浮动鼠标找到合适的位置,按空格键暂停 选择要翻转的3*3模块,找到相邻两个正方体,鼠标点击第一个正方体,并且一直保持鼠标按下的状态直到移到第二个正方体后 ...

  2. VB编写的验证码生成器

    验证码(CAPTCHA)是“Completely AutomatedPublicTuring test to tell Computers andHumansApart”(全自动区分计算机和人类的图灵 ...

  3. JavaUtil_04_验证码生成器

    一.原理 验证码其实就是随机串.原理上可分为两种: 1.简单的验证码 直接通过字母和数字的ASCII码生成.本文采用的验证码就是这种. 2.复杂的验证码 通过一个随机串,一个指定串(如accesske ...

  4. 使用JavaScript在Canvas上画出一片星空

    随着Html5的迅猛发展,画布也变得越来越重要.下面我就写一个关于在canvas上画出一片星空的简单的代码的示例. 理论基础 初始化一个canvas,获得一个用于绘制图形的上下文环境context.并 ...

  5. canvas上的像素操作(图像复制,细调)

    canvas上的像素操作(图像复制,细调) 总结 1.操作对象:ImageData 对象,其实是canvas的像素点集合 2.主要操作: var obj=ctx.getImageData(0,0,10 ...

  6. [Ruby on Rails系列]6、一个简单的暗语生成器与解释器(上)

    [0]Ruby on Rails 系列回顾 [Ruby on Rails系列]1.开发环境准备:Vmware和Linux的安装 [Ruby on Rails系列]2.开发环境准备:Ruby on Ra ...

  7. Canvas上绘制几何图形

    重要的类自定义View组件要重写View组件的onDraw(Canvase)方法,接下来是在该 Canvas上绘制大量的几何图形,点.直线.弧.圆.椭圆.文字.矩形.多边形.曲线.圆角矩形,等各种形状 ...

  8. phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法

    phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法   实这个很简单的只要更改php.ini里三个配置即可.(见下面加粗部分,改成你自己的需求即可) ; Maximum allo ...

  9. 从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理

    从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理 作者:naaoveGI…    文章来源:naaoveGIS    点击数:1145    更新时间: ...

随机推荐

  1. PHP基本的文件和文件夹操作常用的汇总

    资源:http://www.ido321.com/835.html 一.基本文件的操作 文件的基本操作有:文件推断.文件夹推断.文件大小.读写性推断.存在性推断及文件时间等 1: <?php 2 ...

  2. maven hadoop 3.x HADOOP_HOME and hadoop.home.dir are unset Not implemented by the WebHdfsFileSystem FileSystem implementation

    具体异常如下: 解决方案: 删除pom文件中的hadoop-core的依赖,原因:hadoop-core是1.x的产物,在2.x之后已经被hadoop-common取代,我配置的时候同时使用了这两个依 ...

  3. ASP.NET Core & Docker & Jenkins 零基础持续集成实战

    原文:ASP.NET Core & Docker & Jenkins 零基础持续集成实战 一.本系列教程说明 源代码管理工具:Gogs 持续集成工具:Jenkins 容器:Docker ...

  4. hdu1845 Jimmy’s Assignment --- 完整匹配

    意甲冠军: 它需要一个特殊的图,以找到最大匹配.该图的特征是:无向图,度的每个节点3.这是一个双边连接组件(the graph is 2-edge-connected (that is, at lea ...

  5. vmware合并多个虚拟硬盘文件(使用vmware-vdiskmanager.exe)

    有时,当我们创建虚拟机vmware里面的应用程序,我们可能会选择创建分割的虚拟磁盘中的多个文件2GB的文件,这是为了提高复制过程,主要用于存储虚拟机文件系统不支持创建更大的文件.还有种情况是虚拟化物理 ...

  6. 【转】Mybatis传多个参数(三种解决方案)

    转自: http://www.2cto.com/database/201409/338155.html 据我目前接触到的传多个参数的方案有三种. 第一种方案: DAO层的函数方法 Public Use ...

  7. 在sql语句中 inner join ,left join,right join 和on 以及where

    当使用几种join的时候,on是指表连接起来基于的条件,where是对连接的表进行过滤的条件. where 1=1  当我们需要拼接字符串的时候 在基础sql字符串中写上where 1=1 可以不需要 ...

  8. C#中的String.Format介绍

    关键字:C# string.format作者:txw1958原文:http://www.cnblogs.com/txw1958/archive/2012/11/15/csharp-string_for ...

  9. WPF 3D model - Sphere, Cone, and Cylinder

    原文:WPF 3D model - Sphere, Cone, and Cylinder   Extending Visual3D - Sphere, Cone, and Cylinder http: ...

  10. MIME映射(程序映射)

    MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型.是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器 ...