验证码生成器(在TImage.Canvas上写字,很好看)
生成验证码的方式有很多种,如下则是比较简单的实现,且运用了正余弦曲线来扭曲验证码字符。

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上写字,很好看)的更多相关文章
- 【自己给自己题目做】:如何在Canvas上实现魔方效果
最终demo -> 3d魔方 体验方法: 浮动鼠标找到合适的位置,按空格键暂停 选择要翻转的3*3模块,找到相邻两个正方体,鼠标点击第一个正方体,并且一直保持鼠标按下的状态直到移到第二个正方体后 ...
- VB编写的验证码生成器
验证码(CAPTCHA)是“Completely AutomatedPublicTuring test to tell Computers andHumansApart”(全自动区分计算机和人类的图灵 ...
- JavaUtil_04_验证码生成器
一.原理 验证码其实就是随机串.原理上可分为两种: 1.简单的验证码 直接通过字母和数字的ASCII码生成.本文采用的验证码就是这种. 2.复杂的验证码 通过一个随机串,一个指定串(如accesske ...
- 使用JavaScript在Canvas上画出一片星空
随着Html5的迅猛发展,画布也变得越来越重要.下面我就写一个关于在canvas上画出一片星空的简单的代码的示例. 理论基础 初始化一个canvas,获得一个用于绘制图形的上下文环境context.并 ...
- canvas上的像素操作(图像复制,细调)
canvas上的像素操作(图像复制,细调) 总结 1.操作对象:ImageData 对象,其实是canvas的像素点集合 2.主要操作: var obj=ctx.getImageData(0,0,10 ...
- [Ruby on Rails系列]6、一个简单的暗语生成器与解释器(上)
[0]Ruby on Rails 系列回顾 [Ruby on Rails系列]1.开发环境准备:Vmware和Linux的安装 [Ruby on Rails系列]2.开发环境准备:Ruby on Ra ...
- Canvas上绘制几何图形
重要的类自定义View组件要重写View组件的onDraw(Canvase)方法,接下来是在该 Canvas上绘制大量的几何图形,点.直线.弧.圆.椭圆.文字.矩形.多边形.曲线.圆角矩形,等各种形状 ...
- phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法
phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法 实这个很简单的只要更改php.ini里三个配置即可.(见下面加粗部分,改成你自己的需求即可) ; Maximum allo ...
- 从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理
从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理 作者:naaoveGI… 文章来源:naaoveGIS 点击数:1145 更新时间: ...
随机推荐
- android 如何创建配置文件和读配置文件
因为一些配置信息,多处用到的.且以后可能变更的,我想写个.prorperties配置文件给管理起来.在studio中新建一个Assets文件-->新建一个file文件类型为properties文 ...
- Struts2——(8)struts2中文件的上传
通过2种方式模拟单个文件上传,效果如下所示 开发步骤如下: 1.新建一个web工程,导入struts2上传文件所需jar,如下图 目录结构 2.新建Action 第一种方式 ...
- PAT 1051-1060 题解
浏览全部代码:请戳 本文谨代表个人思路,欢迎讨论;) 1051. Pop Sequence (25) 题意 给定 stack 的容量,给定数据的入栈顺序:从 1 开始的正整数序列,在允许随机的出栈操作 ...
- Android如何获得系统版本
如何获得Android系统版本 项目移植中,遇到需要区分不同系统版本的问题.于是查找相关方法如下: android.os.Build类提供了当前系统信息. 可用if (Build.VERSION.SD ...
- UVa 12657 Boxes in a Line(应用双链表)
Boxes in a Line You have n boxes in a line on the table numbered 1 . . . n from left to right. Your ...
- java学习笔记(8)——多线程
进程:是一个程序在其自身的地址空间的一次执行活动. 线程:(区别于进程)线程没有独立的存储空间. 几个概念:时间片 线程 进程 能不能够用多进程代替多线程呢? 两个进程切换时要交换内存空间,而多 ...
- 大型项目使用Automake/Autoconf完成编译配置(标准的编译过程已经变成了简单的三部曲:configure/make/make install,)
使用过开源C/C++项目的同学们都知道,标准的编译过程已经变成了简单的三部曲:configure/make/make install, 使用起来很方便,不像平时自己写代码,要手写一堆复杂的Makefi ...
- SecureCRT 专题
SecureCRT在同一窗口打开多个标签:选中“在标签页中打开”即可 SecureCRT同时向多个tab窗口发送相同的命令 Step by step: 作为管理N台服务器,而又要执行相同命令又不想用脚 ...
- SecureCRT循环检查设备状态
1: #$language = "VBScript" 2: #$interface = "1.0" 3: 4: ' This automatically gen ...
- 使用Qt installer framework制作安装包(不知道是否适合Mac和Linux?)
一.介绍 使用Qt库开发的应用程序,一般有两种发布方式:(1)静态编译发布.这种方式使得程序在编译的时候会将Qt核心库全部编译到一个可执行文件中.其优势是简单单一,所有的依赖库都集中在一起,其缺点也很 ...