反SPAM新思路—换Z-BLOG的验证码!
程序员文章站
2023-11-17 21:06:16
最近我们一些z-blogger都在想做个什么插件拦住spam,当然解决方法也不是没有,就是弄个超强的服务器,可惜搞不起。那……我们只好从spammer的角度来想了。 懂...
最近我们一些z-blogger都在想做个什么插件拦住spam,当然解决方法也不是没有,就是弄个超强的服务器,可惜搞不起。那……我们只好从spammer的角度来想了。
懂一些的人可能知道,spam软件的基本原理是[搜索目标]-进入网站-扫描验证码-ocr-[填写表单]-post。每一步我们都可以加以防范,比较现实的是防止spam软件成功的ocr出验证码。z-blog自带的验证码实在有点弱,干扰点等于没有,感觉可以轻易的分析出验证码里的数字。解决方法就是——换一个验证码程序。
这个验证码程序(就是我现在用的)是从月光留言本里挖出来的,稍加修改,以便适应z-blog。个人认为要编出软件ocr这个验证码是有点难度的,应该可以换取片刻的安宁。当然,这只是权宜之计,如果广泛使用,势必还会有高手来破解的。所以啊……最好官方能弄个服务器,有时候,我觉得商业化或是适当引进投资也是不错的~
目前还在测试效果,3-28晚开始。到目前(07-03-30)为止共收到1个spam(包括被拦截的。),内容和别的spam不一样,应该不是那个垃圾seo网站的作品(很大胆的加了2个链接),而且不是提交在在一般搜索引擎搜索进来的《google加了一个网页恶意软件检测?》,而是在我的留言本。根据referer的结果应该是从主页过去的(也不排除从别的地方进去而没有执行脚本或提交refer信息),怀疑为人工spam(update:haphic也收到了一个同样的。到底是不是人工的?他用的验证码是原版的……),换验证码的效果还需继续观察……
c_validcode.asp代码
<%@ codepage=65001 %>
<% option explicit %>
<%
'on error resume next
%>
<!-- #include file="../c_option.asp" -->
<!-- #include file="../function/c_function.asp" -->
<%
response.buffer=true
call com_creatvalidcode("checkcode")
rem 生成验证码图片
sub com_creatvalidcode(psn)
const codelenmin = 5 '验证码位数范围
const codelenmax = 5 '验证码位数范围
const codds = 2 '杂点出现的机率
const dbttimes = 1 '干扰次数
const posx = 3 '位置随机范围x
const posy = 2 '位置随机范围y
imgwidth = 60 '图像宽(要为4的倍数)
imgheight = 20 '图像高
const camount = 10 '字库数量
const ccode = "0123456789" '字库对应的字符
const unitwidth = 16 '字宽(要为4的倍数)
const unitheight = 15 '字高
const dotslimit = 10 '每次删除有效点的上限(避免无法人为识别)
const trycount = 5 '避免删除有效点超过上限的尝试次数限制
'-----------
randomize
dim i,ii,iii,flag,actunitwidth,imgyuwidth,codelen,imgwidth,imgheight
codelen = codelenmin + cint(rnd*(codelenmax-codelenmin))
if imgwidth mod 4 <> 0 or imgwidth < codelen*unitwidth then imgwidth = codelen*unitwidth
if imgheight < unitheight then imgheight = unitheight
' 禁止缓存
response.expires = -9999
response.addheader "pragma","no-cache"
response.addheader "cache-ctrol","no-cache"
response.contenttype = "image/bmp"
' 颜色的数据(字符,背景)
dim vcolordata(1)
vcolordata(0) = chrb(0) & chrb(0) & chrb(0) ' 蓝0,绿0,红0(黑色)前景色
vcolordata(1) = chrb(255) & chrb(255) & chrb(255) ' 蓝250,绿236,红211(浅蓝色)背景色
' 字符的数据(可以自己修改,如果修改了尺寸,记得把前面的设定也改了)
dim vnumberdata(9)
vnumberdata(0) = "111111111111111111110000000011111110000000000111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111000000000011111110000000011111111111111111111"
vnumberdata(1) = "111111111111111111111100011111111111000001111111111000000111111111001100011111111111110001111111111111000111111111111100011111111111110001111111111111000111111111111100011111111111110001111111111000000000111111100000000011111111111111111111"
vnumberdata(2) = "111111111111111111111100000111111111100000001111111100011100111111100011110011111111111110011111111111110011111111111110011111111111110011111111111110011111111111110011110011111110011111001111111000000000111111100000000011111111111111111111"
vnumberdata(3) = "111111111111111111111000000111111111000000001111111001111110011111100111110011111111111110011111111111100011111111111110001111111111111110011111111111111100111111100111111001111110011111100111111100000000111111111000000111111111111111111111"
vnumberdata(4) = "111111111111111111111111001111111111101100111111111100110011111111110011001111111110011100111111110011110011111110000000000000111000000000000011111111110011111111111111001111111111111100111111111111110011111111111111001111111111111111111111"
vnumberdata(5) = "111111111111111111100000000001111100000000000111110011111111111111001111111111111100111111111111110011000000111111000001111001111111111111100111111111111110011111111111111001111100111111100111110011111110011111100000000011111111111111111111"
vnumberdata(6) = "111111111111111111111100000111111111100000001111111100111110011111100111111111111110011111111111111001000001111111100000000011111110001111100111111001111110011111100111111001111110011111100111111100000000111111111000000111111111111111111111"
vnumberdata(7) = "111111111111111111100000000001111110000000000111111001111110011111100111111001111111111111001111111111111100111111111111100111111111111100111111111111110011111111111111001111111111111100111111111111110011111111111111001111111111111111111111"
vnumberdata(8) = "111111111111111111111000000111111111000000001111111001111110011111100111111001111110011111100111111100000000111111110000000011111111001111001111111001111110011111100111111001111110011111100111111100000000111111111000000111111111111111111111"
vnumberdata(9) = "111111111111111111111000000111111111000000001111111001111110011111100111111001111110011111100111111100000000011111110000001001111111111111100111111111111110011111111111111001111110011111001111111100000000111111111000000111111111111111111111"
' 随机产生字符
dim vcode(), vcodes
redim vcode(codelen-1)
vcodes = getverifynumber
for i = 0 to 4
vcode(i) = cint(mid(vcodes,i+1,1))
vcode(i) = pcd_doubter(vnumberdata(vcode(i)),unitwidth,unitheight,dotslimit,trycount,dbttimes)
next
' 随机产生字符
'dim vcodes
'redim vcode(codelen-1)
'for i = 0 to codelen-1
' vcode(i) = int(rnd * camount)
' vcodes = vcodes & mid(ccode, vcode(i) + 1, 1)
' vcode(i) = pcd_doubter(vnumberdata(vcode(i)),unitwidth,unitheight,dotslimit,trycount,dbttimes)
'next
'session(psn) = vcodes '记录入session
' 输出图像文件头
response.binarywrite chrb(66) & chrb(77) & num2chrb(54+imgwidth*imgheight*3,4) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(54) & chrb(0) & chrb(0) & chrb(0) & chrb(40) & chrb(0) & chrb(0) & chrb(0) & num2chrb(imgwidth,4) & num2chrb(imgheight,4) & chrb(1) & chrb(0)
' 输出图像信息头
response.binarywrite chrb(24) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & num2chrb(imgwidth*imgheight*3,4) & chrb(18) & chrb(11) & chrb(0) & chrb(0) & chrb(18) & chrb(11) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0)
' 生成干扰线
redim noiseline(1,-1)
call makenoise(noiseline,imgwidth,imgheight)
call makenoise(noiseline,imgwidth,imgheight)
' 如果想多画几条直接复制就可以
' call makenoise(noiseline,imgwidth,imgheight)
' 位置随机
actunitwidth = int(imgwidth / codelen)
imgyuwidth = imgwidth - actunitwidth * codelen
redim posary(1,codelen-1)
posary(0,0) = int((rnd)*(posx+(actunitwidth-unitwidth)/2))
posary(1,0) = int((imgheight-unitheight)/2+(1-2*rnd)*posy)
for i=1 to codelen-2
posary(0,i) = int((1-2*rnd)*(posx+(actunitwidth-unitwidth)/2))
posary(1,i) = int((imgheight-unitheight)/2+(1-2*rnd)*posy)
next
if codelen > 1 then
posary(0,codelen-1) = int((rnd)*(posx+(actunitwidth-unitwidth)/2))
posary(1,codelen-1) = int((imgheight-unitheight)/2+(-rnd)*posy)
end if
' 输出图像数据
for i = imgheight-1 to 0 step -1 '行
for ii = 0 to codelen-1 '字
for iii = 0 to actunitwidth-1 '字宽
flag = 0
if onnoiseline(noiseline,ii*actunitwidth+iii,i) then ' 干扰线
flag = 1
elseif getunitdot(posary,vcode,ii,iii,i,unitwidth,unitheight) = "0" then
flag = 1
elseif getunitdot(posary,vcode,ii-1,iii+actunitwidth,i,unitwidth,unitheight) = "0" then
flag = 1
elseif getunitdot(posary,vcode,ii+1,iii-actunitwidth,i,unitwidth,unitheight) = "0" then
flag = 1
end if
' 随机生成杂点
if rnd * 99 + 1 < codds then flag = 1 - flag
response.binarywrite vcolordata(1-flag)
next
next
for ii = 0 to imgyuwidth-1
response.binarywrite vcolordata(1)
next
next
end sub
rem 获取单元的点(考虑位移)
function getunitdot(byref posary,byref vcode,i,byval x,byval y,unitwidth,unitheight)
getunitdot = "1"
if i < 0 or i > ubound(vcode) then exit function
x = x - posary(0,i)
if x < 0 or x >= unitwidth then exit function
y = y - posary(1,i)
if y < 0 or y >= unitheight then exit function
getunitdot = mid(vcode(i),y*unitwidth+x+1,1)
end function
rem 生成干扰线
sub makenoise(byref nl,imgw,unitheight)
dim i,l,x1,y1,x2,y2,dx,dy,deltat
x1 = int(rnd*imgw)
y1 = int(rnd*unitheight)
x2 = int(rnd*imgw)
y2 = int(rnd*unitheight)
dx = x2 - x1
dy = y2 - y1
if abs(dx) > abs(dy) then deltat = abs(dx) else deltat = abs(dy)
if deltat = 0 then exit sub
l = ubound(nl,2)
redim preserve nl(1,l+deltat+1)
l = l + 1
for i = 0 to deltat
nl(0,l+i) = x1 + dx * i \ deltat
nl(1,l+i) = y1 + dy * i \ deltat
next
end sub
rem 判断是否为干扰线上的点
function onnoiseline(byref nl,x,y)
onnoiseline = false
dim i
for i=0 to ubound(nl,2)
if x = nl(0,i) and y = nl(1,i) then
onnoiseline = true
exit for
end if
next
end function
rem 对单个字的点阵进行干扰
rem 干扰思想:在点阵范围内随机产生2个端点,进行连线,以位移较大的一方做横轴,先将连线上的点删除,再将被删除点的纵轴方向上方或下方的点(随机确定)移向被删除点,移动后的空白用背景色补充
function pcd_doubter(byval str,unitwidth,unitheight,dotslimit,trycount,dbttimes)
randomize
dim x1,x2,y1,y2,dx,dy,deltat,i,ii,way,f1,f2
for f1=1 to dbttimes '干扰次数
for f2=1 to trycount '避免删除有效点超过上限的尝试次数限制
'随机确定2个端点
x1 = int(rnd*unitwidth)
x2 = int(rnd*unitwidth)
y1 = int(rnd*unitheight)
y2 = int(rnd*unitheight)
dx = x2 - x1
dy = y2 - y1
if abs(dx) > abs(dy) then deltat = abs(dx) else deltat = abs(dy)
redim ary(1,deltat) '存储连线的点
if deltat = 0 then
ary(0,0) = x1
ary(1,0) = y1
else
ii = 0
for i = 0 to deltat
ary(0,i) = x1 + dx * i \ deltat
ary(1,i) = y1 + dy * i \ deltat
if pcd_getdot(ary(0,i),ary(1,i),str,unitwidth) = "0" then ii = ii + 1
next
' 统计连线上有效点的数量,如未超过有效点上限则跳出循环,执行干扰
if ii <= dotslimit then exit for
end if
next
' 执行干扰(dx,dy改作不同的方向标记用)
if abs(dx) > abs(dy) then dx = 1 else dx = 0
if dx = 1 then
if int(rnd*10) > 4 then
dy = 1
way = -1
else
dy = unitheight - 2
way = 1
end if
else
if int(rnd*10) > 4 then
dy = 1
way = -1
else
dy = unitwidth - 2
way = 1
end if
end if
for i=0 to deltat
for ii=ary(dx,i) to dy step way
call pcd_setdot(ary(0,i)*dx+ii*(1-dx),ary(1,i)*(1-dx)+ii*(dx),str,pcd_getdot(ary(0,i)*dx+(ii+way)*(1-dx),ary(1,i)*(1-dx)+(ii+way)*(dx),str,unitwidth),unitwidth)
next
'添补空白
call pcd_setdot(ary(0,i)*dx+(dy+way)*(1-dx),ary(1,i)*(1-dx)+(dy+way)*(dx),str,"1",unitwidth)
next
next
pcd_doubter = str
end function
rem 得到某点的字符
function pcd_getdot(x,y,str,unitwidth)
pcd_getdot = mid(str,x+1+y*unitwidth,1)
end function
rem 设置某点的字符
sub pcd_setdot(x,y,byref str,newdot,unitwidth)
str = left(str,x+y*unitwidth) & newdot & right(str,len(str)-x-y*unitwidth-1)
end sub
rem 将数字转为bmp需要的格式 lens是目标字节长度
function num2chrb(byval num,lens)
dim ret,i
ret = ""
while (num>0)
ret = ret & chrb(num mod 256)
num = num \ 256
wend
for i=lenb(ret) to lens-1
ret = ret & chrb(0)
next
num2chrb = ret
end function
%>
懂一些的人可能知道,spam软件的基本原理是[搜索目标]-进入网站-扫描验证码-ocr-[填写表单]-post。每一步我们都可以加以防范,比较现实的是防止spam软件成功的ocr出验证码。z-blog自带的验证码实在有点弱,干扰点等于没有,感觉可以轻易的分析出验证码里的数字。解决方法就是——换一个验证码程序。
这个验证码程序(就是我现在用的)是从月光留言本里挖出来的,稍加修改,以便适应z-blog。个人认为要编出软件ocr这个验证码是有点难度的,应该可以换取片刻的安宁。当然,这只是权宜之计,如果广泛使用,势必还会有高手来破解的。所以啊……最好官方能弄个服务器,有时候,我觉得商业化或是适当引进投资也是不错的~
目前还在测试效果,3-28晚开始。到目前(07-03-30)为止共收到1个spam(包括被拦截的。),内容和别的spam不一样,应该不是那个垃圾seo网站的作品(很大胆的加了2个链接),而且不是提交在在一般搜索引擎搜索进来的《google加了一个网页恶意软件检测?》,而是在我的留言本。根据referer的结果应该是从主页过去的(也不排除从别的地方进去而没有执行脚本或提交refer信息),怀疑为人工spam(update:haphic也收到了一个同样的。到底是不是人工的?他用的验证码是原版的……),换验证码的效果还需继续观察……
c_validcode.asp代码
复制代码 代码如下:
<%@ codepage=65001 %>
<% option explicit %>
<%
'on error resume next
%>
<!-- #include file="../c_option.asp" -->
<!-- #include file="../function/c_function.asp" -->
<%
response.buffer=true
call com_creatvalidcode("checkcode")
rem 生成验证码图片
sub com_creatvalidcode(psn)
const codelenmin = 5 '验证码位数范围
const codelenmax = 5 '验证码位数范围
const codds = 2 '杂点出现的机率
const dbttimes = 1 '干扰次数
const posx = 3 '位置随机范围x
const posy = 2 '位置随机范围y
imgwidth = 60 '图像宽(要为4的倍数)
imgheight = 20 '图像高
const camount = 10 '字库数量
const ccode = "0123456789" '字库对应的字符
const unitwidth = 16 '字宽(要为4的倍数)
const unitheight = 15 '字高
const dotslimit = 10 '每次删除有效点的上限(避免无法人为识别)
const trycount = 5 '避免删除有效点超过上限的尝试次数限制
'-----------
randomize
dim i,ii,iii,flag,actunitwidth,imgyuwidth,codelen,imgwidth,imgheight
codelen = codelenmin + cint(rnd*(codelenmax-codelenmin))
if imgwidth mod 4 <> 0 or imgwidth < codelen*unitwidth then imgwidth = codelen*unitwidth
if imgheight < unitheight then imgheight = unitheight
' 禁止缓存
response.expires = -9999
response.addheader "pragma","no-cache"
response.addheader "cache-ctrol","no-cache"
response.contenttype = "image/bmp"
' 颜色的数据(字符,背景)
dim vcolordata(1)
vcolordata(0) = chrb(0) & chrb(0) & chrb(0) ' 蓝0,绿0,红0(黑色)前景色
vcolordata(1) = chrb(255) & chrb(255) & chrb(255) ' 蓝250,绿236,红211(浅蓝色)背景色
' 字符的数据(可以自己修改,如果修改了尺寸,记得把前面的设定也改了)
dim vnumberdata(9)
vnumberdata(0) = "111111111111111111110000000011111110000000000111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111000000000011111110000000011111111111111111111"
vnumberdata(1) = "111111111111111111111100011111111111000001111111111000000111111111001100011111111111110001111111111111000111111111111100011111111111110001111111111111000111111111111100011111111111110001111111111000000000111111100000000011111111111111111111"
vnumberdata(2) = "111111111111111111111100000111111111100000001111111100011100111111100011110011111111111110011111111111110011111111111110011111111111110011111111111110011111111111110011110011111110011111001111111000000000111111100000000011111111111111111111"
vnumberdata(3) = "111111111111111111111000000111111111000000001111111001111110011111100111110011111111111110011111111111100011111111111110001111111111111110011111111111111100111111100111111001111110011111100111111100000000111111111000000111111111111111111111"
vnumberdata(4) = "111111111111111111111111001111111111101100111111111100110011111111110011001111111110011100111111110011110011111110000000000000111000000000000011111111110011111111111111001111111111111100111111111111110011111111111111001111111111111111111111"
vnumberdata(5) = "111111111111111111100000000001111100000000000111110011111111111111001111111111111100111111111111110011000000111111000001111001111111111111100111111111111110011111111111111001111100111111100111110011111110011111100000000011111111111111111111"
vnumberdata(6) = "111111111111111111111100000111111111100000001111111100111110011111100111111111111110011111111111111001000001111111100000000011111110001111100111111001111110011111100111111001111110011111100111111100000000111111111000000111111111111111111111"
vnumberdata(7) = "111111111111111111100000000001111110000000000111111001111110011111100111111001111111111111001111111111111100111111111111100111111111111100111111111111110011111111111111001111111111111100111111111111110011111111111111001111111111111111111111"
vnumberdata(8) = "111111111111111111111000000111111111000000001111111001111110011111100111111001111110011111100111111100000000111111110000000011111111001111001111111001111110011111100111111001111110011111100111111100000000111111111000000111111111111111111111"
vnumberdata(9) = "111111111111111111111000000111111111000000001111111001111110011111100111111001111110011111100111111100000000011111110000001001111111111111100111111111111110011111111111111001111110011111001111111100000000111111111000000111111111111111111111"
' 随机产生字符
dim vcode(), vcodes
redim vcode(codelen-1)
vcodes = getverifynumber
for i = 0 to 4
vcode(i) = cint(mid(vcodes,i+1,1))
vcode(i) = pcd_doubter(vnumberdata(vcode(i)),unitwidth,unitheight,dotslimit,trycount,dbttimes)
next
' 随机产生字符
'dim vcodes
'redim vcode(codelen-1)
'for i = 0 to codelen-1
' vcode(i) = int(rnd * camount)
' vcodes = vcodes & mid(ccode, vcode(i) + 1, 1)
' vcode(i) = pcd_doubter(vnumberdata(vcode(i)),unitwidth,unitheight,dotslimit,trycount,dbttimes)
'next
'session(psn) = vcodes '记录入session
' 输出图像文件头
response.binarywrite chrb(66) & chrb(77) & num2chrb(54+imgwidth*imgheight*3,4) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(54) & chrb(0) & chrb(0) & chrb(0) & chrb(40) & chrb(0) & chrb(0) & chrb(0) & num2chrb(imgwidth,4) & num2chrb(imgheight,4) & chrb(1) & chrb(0)
' 输出图像信息头
response.binarywrite chrb(24) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & num2chrb(imgwidth*imgheight*3,4) & chrb(18) & chrb(11) & chrb(0) & chrb(0) & chrb(18) & chrb(11) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0) & chrb(0)
' 生成干扰线
redim noiseline(1,-1)
call makenoise(noiseline,imgwidth,imgheight)
call makenoise(noiseline,imgwidth,imgheight)
' 如果想多画几条直接复制就可以
' call makenoise(noiseline,imgwidth,imgheight)
' 位置随机
actunitwidth = int(imgwidth / codelen)
imgyuwidth = imgwidth - actunitwidth * codelen
redim posary(1,codelen-1)
posary(0,0) = int((rnd)*(posx+(actunitwidth-unitwidth)/2))
posary(1,0) = int((imgheight-unitheight)/2+(1-2*rnd)*posy)
for i=1 to codelen-2
posary(0,i) = int((1-2*rnd)*(posx+(actunitwidth-unitwidth)/2))
posary(1,i) = int((imgheight-unitheight)/2+(1-2*rnd)*posy)
next
if codelen > 1 then
posary(0,codelen-1) = int((rnd)*(posx+(actunitwidth-unitwidth)/2))
posary(1,codelen-1) = int((imgheight-unitheight)/2+(-rnd)*posy)
end if
' 输出图像数据
for i = imgheight-1 to 0 step -1 '行
for ii = 0 to codelen-1 '字
for iii = 0 to actunitwidth-1 '字宽
flag = 0
if onnoiseline(noiseline,ii*actunitwidth+iii,i) then ' 干扰线
flag = 1
elseif getunitdot(posary,vcode,ii,iii,i,unitwidth,unitheight) = "0" then
flag = 1
elseif getunitdot(posary,vcode,ii-1,iii+actunitwidth,i,unitwidth,unitheight) = "0" then
flag = 1
elseif getunitdot(posary,vcode,ii+1,iii-actunitwidth,i,unitwidth,unitheight) = "0" then
flag = 1
end if
' 随机生成杂点
if rnd * 99 + 1 < codds then flag = 1 - flag
response.binarywrite vcolordata(1-flag)
next
next
for ii = 0 to imgyuwidth-1
response.binarywrite vcolordata(1)
next
next
end sub
rem 获取单元的点(考虑位移)
function getunitdot(byref posary,byref vcode,i,byval x,byval y,unitwidth,unitheight)
getunitdot = "1"
if i < 0 or i > ubound(vcode) then exit function
x = x - posary(0,i)
if x < 0 or x >= unitwidth then exit function
y = y - posary(1,i)
if y < 0 or y >= unitheight then exit function
getunitdot = mid(vcode(i),y*unitwidth+x+1,1)
end function
rem 生成干扰线
sub makenoise(byref nl,imgw,unitheight)
dim i,l,x1,y1,x2,y2,dx,dy,deltat
x1 = int(rnd*imgw)
y1 = int(rnd*unitheight)
x2 = int(rnd*imgw)
y2 = int(rnd*unitheight)
dx = x2 - x1
dy = y2 - y1
if abs(dx) > abs(dy) then deltat = abs(dx) else deltat = abs(dy)
if deltat = 0 then exit sub
l = ubound(nl,2)
redim preserve nl(1,l+deltat+1)
l = l + 1
for i = 0 to deltat
nl(0,l+i) = x1 + dx * i \ deltat
nl(1,l+i) = y1 + dy * i \ deltat
next
end sub
rem 判断是否为干扰线上的点
function onnoiseline(byref nl,x,y)
onnoiseline = false
dim i
for i=0 to ubound(nl,2)
if x = nl(0,i) and y = nl(1,i) then
onnoiseline = true
exit for
end if
next
end function
rem 对单个字的点阵进行干扰
rem 干扰思想:在点阵范围内随机产生2个端点,进行连线,以位移较大的一方做横轴,先将连线上的点删除,再将被删除点的纵轴方向上方或下方的点(随机确定)移向被删除点,移动后的空白用背景色补充
function pcd_doubter(byval str,unitwidth,unitheight,dotslimit,trycount,dbttimes)
randomize
dim x1,x2,y1,y2,dx,dy,deltat,i,ii,way,f1,f2
for f1=1 to dbttimes '干扰次数
for f2=1 to trycount '避免删除有效点超过上限的尝试次数限制
'随机确定2个端点
x1 = int(rnd*unitwidth)
x2 = int(rnd*unitwidth)
y1 = int(rnd*unitheight)
y2 = int(rnd*unitheight)
dx = x2 - x1
dy = y2 - y1
if abs(dx) > abs(dy) then deltat = abs(dx) else deltat = abs(dy)
redim ary(1,deltat) '存储连线的点
if deltat = 0 then
ary(0,0) = x1
ary(1,0) = y1
else
ii = 0
for i = 0 to deltat
ary(0,i) = x1 + dx * i \ deltat
ary(1,i) = y1 + dy * i \ deltat
if pcd_getdot(ary(0,i),ary(1,i),str,unitwidth) = "0" then ii = ii + 1
next
' 统计连线上有效点的数量,如未超过有效点上限则跳出循环,执行干扰
if ii <= dotslimit then exit for
end if
next
' 执行干扰(dx,dy改作不同的方向标记用)
if abs(dx) > abs(dy) then dx = 1 else dx = 0
if dx = 1 then
if int(rnd*10) > 4 then
dy = 1
way = -1
else
dy = unitheight - 2
way = 1
end if
else
if int(rnd*10) > 4 then
dy = 1
way = -1
else
dy = unitwidth - 2
way = 1
end if
end if
for i=0 to deltat
for ii=ary(dx,i) to dy step way
call pcd_setdot(ary(0,i)*dx+ii*(1-dx),ary(1,i)*(1-dx)+ii*(dx),str,pcd_getdot(ary(0,i)*dx+(ii+way)*(1-dx),ary(1,i)*(1-dx)+(ii+way)*(dx),str,unitwidth),unitwidth)
next
'添补空白
call pcd_setdot(ary(0,i)*dx+(dy+way)*(1-dx),ary(1,i)*(1-dx)+(dy+way)*(dx),str,"1",unitwidth)
next
next
pcd_doubter = str
end function
rem 得到某点的字符
function pcd_getdot(x,y,str,unitwidth)
pcd_getdot = mid(str,x+1+y*unitwidth,1)
end function
rem 设置某点的字符
sub pcd_setdot(x,y,byref str,newdot,unitwidth)
str = left(str,x+y*unitwidth) & newdot & right(str,len(str)-x-y*unitwidth-1)
end sub
rem 将数字转为bmp需要的格式 lens是目标字节长度
function num2chrb(byval num,lens)
dim ret,i
ret = ""
while (num>0)
ret = ret & chrb(num mod 256)
num = num \ 256
wend
for i=lenb(ret) to lens-1
ret = ret & chrb(0)
next
num2chrb = ret
end function
%>