Created
October 9, 2015 04:10
-
-
Save yxy/c65f0477d8b545bfce26 to your computer and use it in GitHub Desktop.
A simple captcha generator using PIL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#-*- encoding: utf8 -*- | |
from PIL import Image, ImageDraw, ImageFont | |
import random | |
import string | |
class SimpleCaptchaException(Exception): | |
pass | |
class SimpleCaptcha(object): | |
def __init__(self, length=5, size=(100, 100), fontsize=36, | |
random_text=None, random_bgcolor=None): | |
self.text = "CAPTCHA" | |
self.bgcolor = 255 | |
self.size = size | |
self.fontsize = fontsize | |
self.length = length | |
self.image = None # current captcha image | |
if random_text: | |
self.text = self._random_text() | |
if not self.text: | |
raise SimpleCaptchaException("Field text must not be empty.") | |
if not self.size: | |
raise SimpleCaptchaException("Size must not be empty") | |
if not self.fontsize: | |
raise SimpleCaptchaException("Fontsize must be defined") | |
if random_bgcolor: | |
self.bgcolor = self._random_color() | |
def _center_coords(self, draw, font): | |
width, height = draw.textsize(self.text, font) | |
xy = (self.size[0] - width) / 2., (self.size[1] - height) / 2. | |
return xy | |
def _add_noise_dots(self, draw): | |
"""Add noise dots""" | |
size = self.image.size | |
for _ in range(int(size[0] * size[1] * .1)): | |
xy = (random.randint(0, size[0]), random.randint(0, size[1])) | |
draw.point(xy, fill="white") | |
return draw | |
def _add_noise_lines(self, draw): | |
size = self.image.size | |
for _ in range(8): | |
width = random.randint(1, 2) | |
start = (0, random.randint(0, size[1] - 1)) | |
end = (size[0], random.randint(0, size[1] - 1)) | |
draw.line([start, end], fill="white", width=width) | |
for _ in range(8): | |
start = (-50, -50) | |
end = (size[0] + 10, random.randint(0, size[1] + 10)) | |
draw.arc(start + end, 0, 360, fill="white") | |
return draw | |
def get_captcha(self, size=None, text=None, bgcolor=None): | |
if text is not None: | |
self.text = text | |
if size is not None: | |
self.size = size | |
if bgcolor is not None: | |
self.bgcolor = bgcolor | |
self.image = Image.new("RGB", self.size, self.bgcolor) | |
font_path = "/Library/Fonts/Tahoma.ttf" | |
font = ImageFont.truetype(font_path, self.fontsize) | |
draw = ImageDraw.Draw(self.image) | |
xy = self._center_coords(draw, font) | |
draw.text(xy=xy, text=self.text, font=font) | |
# Add some dot noise | |
draw = self._add_noise_dots(draw) | |
# Add some random lines | |
draw = self._add_noise_lines(draw) | |
self.image.show() | |
return self.image, self.text | |
def _random_text(self): | |
letters = string.ascii_lowercase + string.ascii_uppercase | |
random_text = "" | |
for _ in range(self.length): | |
random_text += random.choice(letters) | |
return random_text | |
def _random_color(self): | |
r = random.randint(0, 255) | |
g = random.randint(0, 255) | |
b = random.randint(0, 255) | |
return (r, g, b) | |
if __name__ == "__main__": | |
sc = SimpleCaptcha(length=7, fontsize=20, random_text=True, | |
random_bgcolor=True) | |
print sc.get_captcha() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment