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