#!/usr/bin/python
|
# -*- coding: GBK -*-
|
#-------------------------------------------------------------------------------
|
#
|
#-------------------------------------------------------------------------------
|
#
|
##@package VerificationCodePic
|
#
|
# @todo: Ëæ»úÉú³ÉͼƬ
|
# @author zhengyang
|
# @date 2010-02-25 17:30
|
# @version 1.4
|
#
|
#
|
# ÐÞ¸Äʱ¼ä ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
|
# @change: 2011-06-20 14:00 zhengyang ÐÞ¸´ÒýÓÃ×ÖÌ屨´í£¬ÐÞ¸´Éú³ÉÃüÃû¸²¸Ç
|
# @change: 2011-06-22 14:00 zhengyang Ôö¼Ó¹¦ÄܶÔ×îÖÕÉú³Éͼ½øÐмôÇÐ
|
# @change: 2011-06-23 12:00 zhengyang Ôö¼Ó×ÖÌå¼ÓÔØ ĬÈϼÓÔØ¸ù·¾¶ÏÂ×ÖÌ壬Ȼºó²éÕÒϵͳ×ÖÌå
|
# @change: 2011-07-11 18:00 Alee Ð޸İü ´óСдÎÊÌ⣬ͼƬ¶àÒ»ÕÅ
|
# @note:
|
#==============================================================================
|
"""Version = 2011-07-11 18:00"""
|
#==============================================================================
|
#µ¼ÈëÈý¸öÄ£¿é
|
#try:
|
# import PIL.Image as Image
|
# import PIL.ImageDraw as ImageDraw
|
# import PIL.ImageFont as ImageFont
|
# import PIL.ImageFilter as ImageFilter
|
#except:
|
# import Image, ImageDraw, ImageFont, ImageFilter
|
#
|
import random
|
import math
|
#import dict4ini._dict4ini
|
import os
|
import sys
|
import time
|
|
|
##¼ÓÔØPY·¾¶
|
# @param importDir µ¼ÈëµÄ½Å±¾Â·¾¶
|
# @return ·µ»ØÖµÎÞÒâÒå
|
def ImportFile(importDir):
|
tmpImportDir = ''
|
for dirName in os.listdir(os.getcwd()):
|
if not os.path.isdir(dirName) or dirName.lower() != importDir:
|
continue
|
|
tmpImportDir = dirName
|
curPath = os.getcwd()+'\\'+tmpImportDir
|
if curPath in sys.path:
|
continue
|
|
sys.path.append(curPath)
|
|
#¼ÓÔØÂ·¾¶£¬±ÜÃâ´óСдÎÊÌâ
|
ImportFile('pil')
|
ImportFile('dict4ini')
|
|
import Image, ImageDraw, ImageFont, ImageFilter
|
import _dict4ini
|
|
config = _dict4ini.DictIni('config.ini', format="%s=%s")
|
|
#---------------------------------------------------------------------------
|
|
|
|
def GetRGBColor(min=0, max=255):
|
return random.choice(range(min, max + 1))
|
|
def GetColor(rgbList):
|
return (GetRGBColor(rgbList[0], rgbList[1]),
|
GetRGBColor(rgbList[2], rgbList[3]),
|
GetRGBColor(rgbList[4], rgbList[5]))
|
|
def Log(*args):
|
print args
|
|
class CodePic():
|
count = 0
|
|
def __init__(self, config):
|
self.background = config.background
|
self.text = config.text
|
self.confusion = config.confusion
|
self.output = config.output
|
|
self.fontDict = {} # {'×ÖÌå': {'×ÖºÅ': fontIns}}
|
|
|
def CreateCodePic(self):
|
|
# ´´½¨±³¾°Í¼Æ¬
|
if self.background.type == 1:
|
image = self.CreateBackImg()
|
elif self.background.type == 2:
|
Log('background.type:%s, not realized'%self.background.type)
|
image = self.CreateBackImg()
|
else:
|
Log('background.type:%s, not defined'%self.background.type)
|
return
|
|
# ÌîдÕýÎÄ
|
colorList, content, value = self.FillText(image)
|
|
# Ìí¼Ó¸ÉÈÅ
|
self.AddConfusion(image, colorList)
|
|
# Êä³ö
|
return self.OutPut(image, content, value)
|
|
|
# Ôö¼Ó¸ÉÈÅ
|
def AddConfusion(self, image, colorList):
|
# ¸ÉÈÅ×ÜÁ¿
|
confusionCount = self.confusion.linecount+self.confusion.pointcount
|
|
# 1.ʹÓÃĬÈÏÑÕÉ« 2.ÿ¸ö¸ÉÈÅËæ»úÑÕÉ« 3.Ëæ»úÒ»¸öÑÕÉ«ËùÓÐ×Ö·û¹²Í¬Ê¹ÓÃ
|
if self.confusion.colortype == 1:
|
color = [self.confusion.defaultcolor]*confusionCount
|
elif self.confusion.colortype == 2:
|
# ´Ó×ÖÌåÑÕÉ«ÖÐÈ¡
|
if self.confusion.randomfontcolor:
|
color = [random.choice(colorList) for i in range(confusionCount)]
|
else:
|
color = [GetColor(self.confusion.randomcolor) for i in range(confusionCount)]
|
elif self.confusion.colortype == 3:
|
# ´Ó×ÖÌåÑÕÉ«ÖÐÈ¡
|
if self.confusion.randomfontcolor:
|
color = [random.choice(colorList)] * confusionCount
|
else:
|
color = [GetColor(self.confusion.randomcolor)] * confusionCount
|
|
draw = ImageDraw.Draw(image)
|
# Ï߸ÉÈÅ
|
if self.confusion.line:
|
for i in range(self.confusion.linecount):
|
#¶¼ÊÇËæ»úµÄ
|
x1 = random.randint(0,self.background.width)
|
x2 = random.randint(0,self.background.width)
|
y1 = random.randint(0,self.background.height)
|
y2 = random.randint(0,self.background.height)
|
size = random.choice(range(self.confusion.size[0], self.confusion.size[1]))
|
draw.line([(x1, y1), (x2, y2)], tuple(color[i]), width=size)
|
# µã¸ÉÈÅ
|
if self.confusion.point:
|
for i in range(self.confusion.pointcount):
|
#¶¼ÊÇËæ»úµÄ
|
x1 = random.randint(0,self.background.width)
|
y1 = random.randint(0,self.background.height)
|
# x2 = random.randint(0,width)
|
# y2 = random.randint(0,height)
|
draw.point((x1, y1), tuple(color[i]))
|
|
# Êä³ö
|
def OutPut(self, image, content, value):
|
|
# 1.Á÷Ë®ºÅ 2.ÄÚÈÝ 3.¶ÔÓ¦µÄº¬Òå
|
if self.output.filenametype == 1:
|
name = CodePic.count
|
elif self.output.filenametype == 2:
|
name = content
|
elif self.output.filenametype == 3:
|
name = value
|
else:
|
Log('output.filenametype.type:%s, not defined'%self.output.filenametype)
|
return False
|
|
# ºó׺
|
ext = self.output.filetype
|
|
path = self.output.outpath
|
|
if os.path.isabs(path):
|
filePath = os.path.join(path, '%s.%s'%(name, ext))
|
else:
|
savePath = os.path.join(os.getcwd(), path)
|
if not os.path.isdir(savePath):
|
os.mkdir(savePath)
|
filePath = os.path.join(os.getcwd(), path, '%s.%s'%(name, ext))
|
|
# ÒѾ´æÔÚÁË
|
if os.path.exists(filePath):
|
return False
|
|
image.filter(ImageFilter.BLUR)
|
box = self.output.crop
|
image = image.crop(box)
|
image.save(filePath)
|
CodePic.count += 1
|
return True
|
|
|
# ´´½¨±³¾°Í¼Æ¬
|
def CreateBackImg(self):
|
#ͼƬ¿í¶È
|
width = self.background.width
|
#ͼƬ¸ß¶È
|
height = self.background.height
|
#±³¾°ÑÕÉ«
|
if self.background.colortype == 1:
|
bgcolor = tuple(self.background.defaultcolor)
|
elif self.background.colortype == 2:
|
bgcolor = GetColor(self.background.randomcolor)
|
else:
|
Log('background.colortype:%s not defined'%self.background.colortype)
|
bgcolor = tuple(self.background.defaultcolor)
|
|
#Éú³É±³¾°Í¼Æ¬
|
image = Image.new('RGB',(width,height),bgcolor)
|
return image
|
|
|
# Ìî³äÕýÎÄ
|
def FillText(self, image):
|
#ÐÂͼƬ
|
newImage = image.copy() #ÉèÖñ¸·Ý
|
newImageEx = image.copy() #ÉèÖñ¸·Ý
|
|
colorList = []
|
draw = ImageDraw.Draw(newImage)
|
|
content, value = self.GetContent(self.text)
|
|
# 1.ʹÓÃĬÈÏÑÕÉ« 2.ÿ¸ö×Ö·ûËæ»úÑÕÉ« 3.Ëæ»úÒ»¸öÑÕÉ«ËùÓÐ×Ö·û¹²Í¬Ê¹ÓÃ
|
if self.text.colortype == 1:
|
colorList = len(content) * [self.text.defaultcolor]
|
elif self.text.colortype == 2:
|
colorList = [GetColor(self.text.randomcolor) for i in range(len(content))]
|
elif self.text.colortype == 3:
|
colorList = len(content) * [GetColor(self.text.randomcolor)]
|
else:
|
Log('text.colortype:%s not defined'%self.text.colortype)
|
|
# 1.ʹÓÃĬÈÏ×ÖÌå 2.ÿ¸ö×Ö·ûËæ»ú×ÖÌå 3.Ëæ»úÒ»¸ö×ÖÌåËùÓÐ×Ö·û¹²Í¬Ê¹ÓÃ
|
if self.text.fonttype == 1:
|
fontTypeList = len(content) * [self.defaultfont]
|
elif self.text.fonttype == 2:
|
fontTypeList = [random.choice(self.text.randomfont) for i in range(len(content))]
|
elif self.text.fonttype == 3:
|
fontTypeList = len(content) * [random.choice(self.text.randomfont)]
|
else:
|
Log('text.fonttype:%s not defined'%self.text.fonttype)
|
|
# ¿ªÊ¼»æÖÆ
|
for k, v in enumerate(content):
|
hpos = random.choice(range(self.text.voffset[0], self.text.voffset[1]))+k*self.text.hspace
|
vpos = random.choice(range(self.text.voffset[0], self.text.voffset[1]))
|
|
fontSize = random.choice(self.text.fontsize)
|
font = None
|
if self.fontDict.has_key(fontTypeList[k]):
|
if self.fontDict[fontTypeList[k]].has_key(fontSize):
|
font = self.fontDict[fontTypeList[k]][fontSize]
|
if not font:
|
|
filename = fontTypeList[k] + '.ttf'
|
filePath = os.path.join(os.getcwd(), filename)
|
if os.path.isfile(filePath):
|
filaname = filePath
|
else:
|
windir = os.environ.get("WINDIR")
|
if windir:
|
filename = os.path.join(windir, "fonts", filename)
|
font = ImageFont.truetype(filename, fontSize)
|
self.fontDict[fontTypeList[k]] = {}
|
self.fontDict[fontTypeList[k]][fontSize] = font
|
|
fontcolor = colorList[k]
|
draw.text((self.text.starth + hpos, self.text.startv + vpos),v,font=font,fill=fontcolor)
|
del draw
|
|
# ÖÆ×÷ŤÇú
|
# hdistortion = 0.5
|
# vdistortion = 0
|
#loadÏñËØ
|
newPix = newImage.load()
|
pix = newImageEx.load()
|
|
offset = 0
|
for y in range(0, self.background.height):
|
offset += self.text.hdistortion
|
for x in range(0, self.background.width):
|
#еÄx×ø±êµã
|
newx = x - offset
|
#Äã¿ÉÒÔÊÔÊÔÈçϵÄЧ¹û
|
# newx = x + math.sin(3.0*math.pi*y/height)*8
|
if 0 < newx < self.background.width:
|
#°ÑÔ´ÏñËØÍ¨¹ýÆ«ÒÆµ½ÐµÄÏñËØµã
|
pix[newx,y] = newPix[x,y]
|
|
|
newPix = newImageEx.load()
|
pix = image.load()
|
offset = 0
|
for x in range(0, self.background.width):
|
offset += self.text.vdistortion
|
for y in range(0, self.background.height):
|
#еÄy×ø±êµã
|
newy = y - offset
|
#Äã¿ÉÒÔÊÔÊÔÈçϵÄЧ¹û
|
# newx = x + math.sin(3.0*math.pi*y/height)*8
|
if 0 < newy < self.background.height:
|
#°ÑÔ´ÏñËØÍ¨¹ýÆ«ÒÆµ½ÐµÄÏñËØµã
|
pix[x,newy] = newPix[x,y]
|
|
return colorList, ''.join(content), value # ·µ»ØÕýÎÄÓõ½µÄÉ«²Ê
|
|
|
# »ñÈ¡ÎÄ×Ö
|
def GetContent(self, text):
|
|
strList = [] # ×Ö·ûºòÑ¡Áбí
|
retText = [] # ·µ»ØµÄÎÄ×ÖÁбí
|
|
# ËùÓÐ×Ö·ûͳһ²ÉÑù
|
if text.createtype == 1:
|
if text.expr and random.random() < text.exprrate:
|
element = text.exprelem
|
digit = [random.choice(range(element[0],element[1])), random.choice(range(element[0],element[1]))]
|
operator = random.choice(text.exproperator)
|
if operator == '-' and not text.exprallownegsub:
|
digit.sort()
|
retText = list(str(digit[1])) + [operator] + list(str(digit[0])) + ['=']
|
|
#¼ÆË㹫ʽֵ
|
expr = ''.join(retText[:-1])
|
transDict = {
|
'+':'+',
|
'-':'-'
|
}
|
|
for k, v in transDict.items():
|
if k in expr:
|
temp = expr.replace(k, v)
|
value = eval(temp)
|
return retText, value
|
|
if text.digital:
|
strList = strList + range(0, 10)
|
if text.supper:
|
strList = strList + [chr(i) for i in range(ord('A'), ord('Z') + 1)]
|
if text.lower:
|
strList = strList + [chr(i) for i in range(ord('a'), ord('z') + 1)]
|
for i in range(text.chrcount):
|
retText.append(str(random.choice(strList)))
|
|
elif text.createtype == 2:
|
retText = [str(random.choice(text['chr%s'%i])) for i in range(text.chrcount)]
|
else:
|
Log('text.createtype:%s not defined'%self.text.createtype)
|
|
value = ''.join(retText)
|
if text.ignoresupper:
|
value = value.lower()
|
return retText, value
|
|
|
maker = CodePic(config)
|
|
def Make(count):
|
stime = time.time()
|
temp = 0
|
while temp < count:
|
if maker.CreateCodePic():
|
print 'making %s/%s ...'%(temp, count)
|
temp += 1
|
print 'time cost:', time.time() - stime
|
|
|
if __name__ == '__main__':
|
|
if len(sys.argv) == 2:
|
count = int(sys.argv[1])
|
Make(count)
|
|
else:
|
Make(10)
|
|
|