#!/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)   
 | 
      
 | 
      
 |