87
|
1 """ Captcha.Visual.Backgrounds
|
|
2
|
|
3 Background layers for visual CAPTCHAs
|
|
4 """
|
|
5 #
|
|
6 # PyCAPTCHA Package
|
|
7 # Copyright (C) 2004 Micah Dowty <micah@navi.cx>
|
|
8 #
|
|
9
|
|
10 from Captcha.Visual import Layer, Pictures
|
|
11 import random, os
|
|
12 import ImageDraw, Image
|
|
13
|
|
14
|
|
15 class SolidColor(Layer):
|
|
16 """A solid color background. Very weak on its own, but good
|
|
17 to combine with other backgrounds.
|
|
18 """
|
|
19 def __init__(self, color="white"):
|
|
20 self.color = color
|
|
21
|
|
22 def render(self, image):
|
|
23 image.paste(self.color)
|
|
24
|
|
25
|
|
26 class Grid(Layer):
|
|
27 """A grid of lines, with a given foreground color.
|
|
28 The size is given in pixels. The background is transparent,
|
|
29 so another layer (like SolidColor) should be put behind it.
|
|
30 """
|
|
31 def __init__(self, size=16, foreground="black"):
|
|
32 self.size = size
|
|
33 self.foreground = foreground
|
|
34 self.offset = (random.uniform(0, self.size),
|
|
35 random.uniform(0, self.size))
|
|
36
|
|
37 def render(self, image):
|
|
38 draw = ImageDraw.Draw(image)
|
|
39
|
|
40 for i in xrange(image.size[0] / self.size + 1):
|
|
41 draw.line( (i*self.size+self.offset[0], 0,
|
|
42 i*self.size+self.offset[0], image.size[1]), fill=self.foreground)
|
|
43
|
|
44 for i in xrange(image.size[0] / self.size + 1):
|
|
45 draw.line( (0, i*self.size+self.offset[1],
|
|
46 image.size[0], i*self.size+self.offset[1]), fill=self.foreground)
|
|
47
|
|
48
|
|
49 class TiledImage(Layer):
|
|
50 """Pick a random image and a random offset, and tile the rendered image with it"""
|
|
51 def __init__(self, imageFactory=Pictures.abstract):
|
|
52 self.tileName = imageFactory.pick()
|
|
53 self.offset = (random.uniform(0, 1),
|
|
54 random.uniform(0, 1))
|
|
55
|
|
56 def render(self, image):
|
|
57 tile = Image.open(self.tileName)
|
|
58 for j in xrange(-1, int(image.size[1] / tile.size[1]) + 1):
|
|
59 for i in xrange(-1, int(image.size[0] / tile.size[0]) + 1):
|
|
60 dest = (int((self.offset[0] + i) * tile.size[0]),
|
|
61 int((self.offset[1] + j) * tile.size[1]))
|
|
62 image.paste(tile, dest)
|
|
63
|
|
64
|
|
65 class CroppedImage(Layer):
|
|
66 """Pick a random image, cropped randomly. Source images should be larger than the CAPTCHA."""
|
|
67 def __init__(self, imageFactory=Pictures.nature):
|
|
68 self.imageName = imageFactory.pick()
|
|
69 self.align = (random.uniform(0,1),
|
|
70 random.uniform(0,1))
|
|
71
|
|
72 def render(self, image):
|
|
73 i = Image.open(self.imageName)
|
|
74 image.paste(i, (int(self.align[0] * (image.size[0] - i.size[0])),
|
|
75 int(self.align[1] * (image.size[1] - i.size[1]))))
|
|
76
|
|
77
|
|
78 class RandomDots(Layer):
|
|
79 """Draw random colored dots"""
|
|
80 def __init__(self, colors=("white", "black"), dotSize=4, numDots=400):
|
|
81 self.colors = colors
|
|
82 self.dotSize = dotSize
|
|
83 self.numDots = numDots
|
|
84 self.seed = random.random()
|
|
85
|
|
86 def render(self, image):
|
|
87 r = random.Random(self.seed)
|
|
88 for i in xrange(self.numDots):
|
|
89 bx = int(r.uniform(0, image.size[0]-self.dotSize))
|
|
90 by = int(r.uniform(0, image.size[1]-self.dotSize))
|
|
91 image.paste(r.choice(self.colors), (bx, by,
|
|
92 bx+self.dotSize-1,
|
|
93 by+self.dotSize-1))
|
|
94
|
|
95 ### The End ###
|