Skip to content

Commit 1456b67

Browse files
added compatibility with py2/py3 & added new **kw params
1 parent 959a9c9 commit 1456b67

File tree

3 files changed

+109
-30
lines changed

3 files changed

+109
-30
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# images created by a simple test:
2+
*.jpg
3+
*.png
4+
*.jpeg

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# randcaptcha
2-
Genera una imagen de una captcha random | generate a random captcha image with Python
2+
Genera una imagen de una captcha random | generate a random captcha image with Python2 or Python3
33

44

55
## Dependencies:
@@ -34,3 +34,9 @@ CreateImageCaptcha(..) return text content on captcha and filename of captcha.
3434

3535

3636

37+
## Last Changes:
38+
---------------
39+
40+
## version 0.2
41+
42+
Added params **kw, can use new param "rotate" for specify random angle of rotation. Module compatibility with Py2 and Py3

randcaptcha.py

Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
return two strings (text random, path of image).
77
88
9+
see help(module) for use
10+
11+
changes on versions:
12+
- from 0.1 to 0.2
13+
Added kw args, rotate arg change the angle of rotates
14+
Added retro-compatibility with python 2.7 (compatibility with py3 and py2)
15+
916
---------------------------------------------------------------------------------
1017
1118
MIT License
@@ -38,20 +45,35 @@
3845

3946

4047

41-
version = 0.1;
48+
version = 0.2;
4249

4350
_textRandom = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
44-
_textRandom = _textRandom.upper();
4551
_textRandom += "0123456789";
4652

4753

4854
def _invertColor(rgb):
4955
return tuple([255-color for color in rgb]);
5056

57+
def _getTextLength(font_pillow, text):
58+
#calculate the width of char or text
59+
if hasattr(font_pillow, "getlength"):
60+
#python3x
61+
return int(font_pillow.getlength(text));
62+
else:
63+
#python2x (will be deprecated method on python3)
64+
return int(font_pillow.getsize(text)[0]);
65+
66+
def _getRandomContrastColor(background):
67+
#select a random color with a contrast:
68+
color = background;
69+
while abs(sum(background) - sum(color)) < 300:
70+
color = tuple([randint(0, 255) for i in range(3)]);
71+
return color;
5172

5273

74+
_validOptions = ("rotate",);
5375
def CreateImageCaptcha(fontnames, fontsize, filename_out=None,
54-
length=5, valid=_textRandom, background=(200, 200, 200), addgarbage=True):
76+
length=5, valid=_textRandom, background=(200, 200, 200), addgarbage=True, **kw):
5577

5678
"""
5779
Generate a random image for captcha and save the image on a file.
@@ -90,8 +112,32 @@ def CreateImageCaptcha(fontnames, fontsize, filename_out=None,
90112
addgarbage: use a True or False boolean, this flag controls additional drawing of line shapes,
91113
default: True
92114
115+
**kw extras:
116+
rotate: the range of random rotations of a char,
117+
can be a pair of angles from -360 to 360 each.
118+
Can set this param to None value (no rotations, simple)
119+
default: (-60, 60)
120+
93121
"""
94122

123+
for opt in kw:
124+
if not opt in _validOptions:
125+
raise Exception("option %s not in (%s)" % (opt, str(_validOptions)));
126+
127+
128+
rotate = kw.get("rotate", (-60, 60));
129+
try:
130+
#need validate the rotate param
131+
if rotate != None:
132+
minAngle, maxAngle = rotate;
133+
assert minAngle >= -360 and minAngle <= 360;
134+
assert maxAngle >= -360 and maxAngle <= 360;
135+
136+
except:
137+
raise Exception(
138+
"""param -rotate can be a pair of angles from -360 to 360 each,
139+
example: (-100, 100) or (10, 60) or None (do not rotate, no angle).""");
140+
95141
assert length > 0;
96142

97143
#creating text random:
@@ -116,32 +162,44 @@ def CreateImageCaptcha(fontnames, fontsize, filename_out=None,
116162
heightFont = sum(font.getmetrics());
117163

118164
#drawing images of chars:
119-
#draw = ImageDraw.Draw(image);
120-
rotatedImagesChar = [];
121-
for char in text:
122-
widthChar = int(font.getlength(char));
123-
124-
#select a random color with a contrast:
125-
color = background;
126-
while abs(sum(background) - sum(color)) < 300:
127-
color = tuple([randint(0, 255) for i in range(3)]);
128-
129-
#new image char rotated:
130-
imgChar = Image.new("RGB", (widthChar, heightFont), background);
131-
ImageDraw.Draw(imgChar).text((0, 0), char, color, font=font);
132-
imgChar = imgChar.rotate(randint(-60, 60), expand=True, fillcolor=background);
133-
134-
rotatedImagesChar.append(imgChar)
165+
166+
if rotate != None:
167+
rotatedImagesChar = [];
168+
for char in text:
169+
#calculate the width of char:
170+
widthChar = _getTextLength(font, char);
135171

136-
#create image main container:
137-
tatalWidth = pad + sum([img.width+pad for img in rotatedImagesChar]);
138-
lastx = pad;
139-
imgCaptcha = Image.new("RGB", (tatalWidth, heightFont+pad*2), background);
172+
#select a random color with a contrast:
173+
color = _getRandomContrastColor(background);
174+
175+
#new image char rotated:
176+
imgChar = Image.new("RGB", (widthChar, heightFont), background);
177+
ImageDraw.Draw(imgChar).text((0, 0), char, color, font=font);
178+
imgChar = imgChar.rotate(randint(minAngle, maxAngle),
179+
expand=True, fillcolor=background);
180+
181+
rotatedImagesChar.append(imgChar)
182+
183+
tatalWidth = pad + sum([img.width+pad for img in rotatedImagesChar]);
140184

141-
#add images into container:
142-
for imgChar in rotatedImagesChar:
143-
imgCaptcha.paste(imgChar, (lastx, pad));
144-
lastx += imgChar.width+pad;
185+
#create image main container:
186+
imgCaptcha = Image.new("RGB", (tatalWidth, heightFont+pad*2), background);
187+
188+
lastx = pad;
189+
#add images into container:
190+
for imgChar in rotatedImagesChar:
191+
imgCaptcha.paste(imgChar, (lastx, pad));
192+
lastx += imgChar.width+pad;
193+
else:
194+
#no-rotated chars:
195+
tatalWidth = _getTextLength(font, text) + (pad*(len(text)+1));
196+
imgCaptcha = Image.new("RGB", (tatalWidth, heightFont+pad*2), background);
197+
draw = ImageDraw.Draw(imgCaptcha);
198+
lastx = pad;
199+
for char in text:
200+
color = _getRandomContrastColor(background);
201+
draw.text((lastx, pad), char, color, font=font);
202+
lastx += _getTextLength(font, char) + pad;
145203

146204
#add garbage ? :
147205
if addgarbage:
@@ -173,10 +231,21 @@ def CreateImageCaptcha(fontnames, fontsize, filename_out=None,
173231

174232
if __name__ == "__main__":
175233

176-
text, fname = CreateImageCaptcha(["impact", "arial"], 25, filename_out="micaptcha.jpg", background=(20, 20, 20));
234+
from time import time as timer;
235+
236+
t1 = timer();
237+
text, fname = CreateImageCaptcha(["impact", "arial"], 25,
238+
filename_out="micaptcha.jpg", background=(20, 20, 20));
239+
240+
t1 = timer()-t1;
177241

178242
print(text, fname);
243+
print("%f seconds transcurred" % t1);
179244

180245
#windows:
181246
from os import startfile;
182-
startfile(fname)
247+
startfile(fname);
248+
249+
input("Pause - press enter to exit...");
250+
251+

0 commit comments

Comments
 (0)