Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache) ’不缓存
Dim x, y, x1, y1 As Single
Dim PenWidth1, PenWidth2, VerifyVharFont As Integer
Dim VerifyChar As String = RndChar(4) ’RndChar是一个自定义函数
Dim Img As System.Drawing.Bitmap
Dim g As Graphics
Dim backBrush As Brush = Brushes.DimGray
Dim textBrush As Brush = Brushes.Black
VerifyVharFont = Int(7 * Rnd()) + 14 ’验证码字符字体大小随机生成
Dim textFont As New Font("Arial", VerifyVharFont, FontStyle.Strikeout) ’验证码字体
Dim ms As MemoryStream
Dim gWidth As Integer = Int(Len(VerifyChar)) * VerifyVharFont + VerifyVharFont ’验证区宽度。如果字符都为W,不加宽是不行的
Img = New Bitmap(gWidth, 30) ’验证区高度
’生成随机背景颜色
Dim nRed, nGreen, nBlue As Integer ’ 背景的三元色
Dim rd = New Random ’(CInt(System.DateTime.Now.Ticks))
nRed = rd.Next(255) Mod 128 + 128
nGreen = rd.Next(255) Mod 128 + 128
nBlue = rd.Next(255) Mod 128 + 128
’在图片框picCanvas上面建立一个新的空白Graphics
g = Graphics.FromImage(Img)
’填充位图背景
g.FillRectangle(New SolidBrush(System.Drawing.Color.FromArgb(nRed, nGreen, nBlue)), 0, 0, Img.Width, Img.Height)
’随机输出噪音线
Dim i As Int32
For i = 0 To 2
Randomize()
x = Img.Width * Rnd()
y = Img.Height * Rnd()
x1 = Img.Width * Rnd()
y1 = Img.Height * Rnd()
PenWidth1 = 2 * Rnd() ’修改参数可获得不同的效果
g.DrawLine(New Pen(backBrush, PenWidth1), x, y, x1, y1)
Next
’随机输出噪点
PenWidth2 = 2 ’修改参数可获得不同的效果
For i = 0 To 10
Randomize()
x = Img.Width * Rnd()
y = Img.Height * Rnd()
nRed = rd.Next(255) Mod 128 + 128
nGreen = rd.Next(255) Mod 128 + 128
nBlue = rd.Next(255) Mod 128 + 128
g.DrawRectangle(New Pen(Color.FromArgb(nRed, nGreen, nBlue), PenWidth2), x, y, 1, 1)
Next
’文字的位置
x = 16 * Rnd() - 6 ’随机产生X轴位置,增加程序识别难度
y = 0
’随机画3D背景
Dim S3d As Single = Rnd()
If S3d > 0.9 Then
For i = 1 To 0 Step -1
g.DrawString(VerifyChar, textFont, backBrush, x - i, y + i)
Next
End If
’将全局变换平移(x, y),也就是使画布上将要画的所有内容向左边移动x,向下移动y
g.TranslateTransform(1.5, 1)
’做切变,将原始矩形的下边缘水平移动矩形高度的0.2倍
Dim textTransform As Matrix = g.Transform
textTransform.Shear(0.2, 0)
g.Transform = textTransform
’画出文字
g.DrawString(VerifyChar, textFont, textBrush, x, y)
Me.Session("VerifyChar") = VerifyChar ’将验证字符写入Session,供前台调用
’扭曲验证字符。TwistImage参数可自行修改
Dim Twist1, Twist2 As Single
If S3d > 0.9 Then ’3D背景减少扭曲
Twist1 = 0
Twist2 = 0
Else
Twist1 = Rnd() * 3 ’扭曲参数随机生成
Twist2 = Rnd() * 2 ’扭曲参数随机生成
End If
Img = TwistImage(Img, True, -Twist1, -Twist2)
Img = TwistImage(Img, False, Twist1, Twist2) ’多扭曲几次也没关系,只是消耗服务器资源多些
ms = New MemoryStream
Img.Save(ms, ImageFormat.Png)
Response.ClearContent() ’需要输出图象信息 要修改HTTP头
Response.ContentType = "image/Png"
Response.BinaryWrite(ms.ToArray())
g.Dispose()
Img.Dispose()
Response.End()
End Sub
’函数名称:RndChar
’函数参数:VcodeNum--设定返回随机字符串的位数
’函数功能:产生指定长度的由数字和字符组成的随机字符串
Function RndChar(ByVal VcodeNum) As String
Dim Vchar As String = "3,3,5,5,6,6,7,7,9,9,A,C,E,F,G,H,K,L,M,N,P,R,T,X,Y,Z" ’定义验证码字符及出现频次
Dim VcArray() As String = Split(Vchar, ",") ’将字符串生成数组
Vchar = ""
Dim i As Byte
For i = 0 To Int(VcodeNum * Rnd()) + 1 ’确保最少2个字符,最多VcodeNum+1个字符
Randomize()
Vchar = Vchar & VcArray(Int(25 * Rnd())) ’数组一般从0开始读取,所以这里为25*Rnd
Next
Return Vchar
End Function
’函数名称:TwistImage
’函数参数: dMultValue-波形的幅度倍数;dPhase波形的起始相位,取值区间[0-2*PI);bXDir-扭曲方式
’函数功能:正弦曲线Wave扭曲图片。函数可以迭加使用,以获得不同方式不同程度的效果
’这个天才的函数,已经无法考证出处了。感谢原作者!
Public Function TwistImage(ByVal srcBmp As Bitmap, ByVal bXDir As Boolean, ByVal dMultValue As Double, ByVal dPhase As Double) As Bitmap
Dim destBmp = New Bitmap(srcBmp.Width, srcBmp.Height)
Dim dBaseAxisLen As Double = IIf(bXDir, CDbl(destBmp.Height), CDbl(destBmp.Width)) ’ToDo: Unsupported feature: conditional (?) operator.
Dim i As Integer
For i = 0 To destBmp.Width - 1
Dim j As Integer
For j = 0 To destBmp.Height - 1
Dim dx As Double = 0
dx = IIf(bXDir, PI2 * CDbl(j) / dBaseAxisLen, PI2 * CDbl(i) / dBaseAxisLen) ’ToDo: Unsupported feature: conditional (?) operator.
dx += dPhase
Dim dy As Double = Math.Sin(dx)
’ 取得当前点的颜色
Dim nOldX As Integer = 0
Dim nOldY As Integer = 0
nOldX = IIf(bXDir, i + CInt(dy * dMultValue), i) ’ToDo: Unsupported feature: conditional (?) operator.
nOldY = IIf(bXDir, j, j + CInt(dy * dMultValue)) ’ToDo: Unsupported feature: conditional (?) operator.
Dim color As System.Drawing.Color = srcBmp.GetPixel(i, j)
If nOldX >= 0 And nOldX < destBmp.Width And nOldY >= 0 And nOldY < destBmp.Height Then
destBmp.SetPixel(nOldX, nOldY, color)
End If
Next j
Next i
Return destBmp
End Function
End Class