annotate data_generation/transformations/pycaptcha/Captcha/Visual/Text.py @ 254:dd2df78fcf47

added option to pipeline and gimp_script to produce NIST-friendly data
author Xavier Glorot <glorotxa@iro.umontreal.ca>
date Wed, 17 Mar 2010 13:57:15 -0400
parents 81f8466dc121
children
rev   line source
87
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
1 """ Captcha.Visual.Text
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
2
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
3 Text generation for visual CAPTCHAs.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
4 """
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
5 #
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
6 # PyCAPTCHA Package
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
7 # Copyright (C) 2004 Micah Dowty <micah@navi.cx>
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
8 #
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
9
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
10 import random, os
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
11 from Captcha import Visual, File
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
12 import ImageFont, ImageDraw
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
13
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
14
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
15 class FontFactory(File.RandomFileFactory):
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
16 """Picks random fonts and/or sizes from a given list.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
17 'sizes' can be a single size or a (min,max) tuple.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
18 If any of the given files are directories, all *.ttf found
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
19 in that directory will be added.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
20 """
132
25b7c1f20949 Adapted pycaptcha to get fonts in /Tmp/allfonts local folder
boulanni <nicolas_boulanger@hotmail.com>
parents: 87
diff changeset
21 extensions = [".ttf", ".TTF"]
87
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
22 basePath = "fonts"
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
23
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
24 # arguments variables a modifier pour mettre le chemin vers les fontes.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
25 def __init__(self, sizes, *fileNames):
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
26 File.RandomFileFactory.__init__(self, *fileNames)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
27
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
28 if type(sizes) is tuple:
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
29 self.minSize = sizes[0]
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
30 self.maxSize = sizes[1]
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
31 else:
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
32 self.minSize = sizes
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
33 self.maxSize = sizes
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
34
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
35 def pick(self):
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
36 """Returns a (fileName, size) tuple that can be passed to ImageFont.truetype()"""
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
37 fileName = File.RandomFileFactory.pick(self)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
38 size = int(random.uniform(self.minSize, self.maxSize) + 0.5)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
39 return (fileName, size)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
40
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
41 # Predefined font factories
184
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
42 defaultFontFactory = FontFactory(25, "/Tmp/allfonts")
87
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
43 #defaultFontFactory = FontFactory((30, 40), "vera")
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
44
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
45 class TextLayer(Visual.Layer):
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
46 """Represents a piece of text rendered within the image.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
47 Alignment is given such that (0,0) places the text in the
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
48 top-left corner and (1,1) places it in the bottom-left.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
49
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
50 The font and alignment are optional, if not specified one is
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
51 chosen randomly. If no font factory is specified, the default is used.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
52 """
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
53 def __init__(self, text,
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
54 alignment = None,
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
55 font = None,
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
56 fontFactory = None,
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
57 textColor = "white",
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
58 borderSize = 0,
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
59 borderColor = None,
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
60 ):
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
61 if fontFactory is None:
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
62 global defaultFontFactory
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
63 fontFactory = defaultFontFactory
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
64
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
65 if font is None:
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
66 font = fontFactory.pick()
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
67
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
68 if alignment is None:
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
69 alignment = (random.uniform(0,1),
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
70 random.uniform(0,1))
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
71
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
72 self.text = text
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
73 self.alignment = alignment
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
74 self.font = font
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
75 self.textColor = textColor
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
76 self.borderSize = borderSize
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
77 self.borderColor = borderColor
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
78
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
79 def render(self, img):
184
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
80
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
81 i=1
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
82 while True:
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
83 try:
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
84 font = ImageFont.truetype(*self.font)
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
85 break
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
86 except:
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
87 print "try#", i, self.font
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
88 i += 1
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
89 if i>10: raise
81f8466dc121 Transient exception handling in captchas (ie. lorsque le NFS est temporairement inaccessible)
boulanni <nicolas_boulanger@hotmail.com>
parents: 167
diff changeset
90
87
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
91 textSize = font.getsize(self.text)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
92 draw = ImageDraw.Draw(img)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
93
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
94 # Find the text's origin given our alignment and current image size
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
95 x = int((img.size[0] - textSize[0] - self.borderSize*2) * self.alignment[0] + 0.5)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
96 y = int((img.size[1] - textSize[1] - self.borderSize*2) * self.alignment[1] + 0.5)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
97
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
98 # Draw the border if we need one. This is slow and ugly, but there doesn't
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
99 # seem to be a better way with PIL.
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
100 if self.borderSize > 0:
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
101 for bx in (-1,0,1):
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
102 for by in (-1,0,1):
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
103 if bx and by:
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
104 draw.text((x + bx * self.borderSize,
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
105 y + by * self.borderSize),
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
106 self.text, font=font, fill=self.borderColor)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
107
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
108 # And the text itself...
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
109 draw.text((x,y), self.text, font=font, fill=self.textColor)
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
110
4775b4195b4b code pour la generation de captchas
goldfinger
parents:
diff changeset
111 ### The End ###