from io import BytesIO
import random, math
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from flask import Flask,session, make_response


class vieCode:
    __fontSize = 20  # 字体大小
    __width = 120  # 画布宽度
    __heigth = 45  # 画布高度
    __length = 5  # 验证码长度
    __draw = None  # 画布
    __img = None  # 图片资源
    __code = None  # 验证码字符
    __str = None  # 自定义验证码字符集
    __inCurve = True  # 是否画干扰线
    __inNoise = True  # 是否画干扰点
    __type = 2  # 验证码类型 1、纯字母  2、数字字母混合
    __fontPatn = '1.ttf'  # 字体

    def GetCodeImage(self, size=80, length=5):
        '''获取验证码图片
           @param int size 验证码大小
           @param int length 验证码长度
        '''
        # 准备基础数据
        self.__length = length
        self.__fontSize = size
        self.__width = self.__fontSize * self.__length
        self.__heigth = int(self.__fontSize * 1.5)

        # 生成验证码图片
        self.__createCode()
        self.__createImage()
        self.__createNoise()
        self.__printString()
        self.__cerateFilter()

        return self.__img, self.__code

    def __cerateFilter(self):
        '''模糊处理'''
        self.__img = self.__img.filter(ImageFilter.BLUR)
        filter = ImageFilter.ModeFilter(8)
        self.__img = self.__img.filter(filter)

    def __createCode(self):
        '''创建验证码字符'''
        # 是否自定义字符集合
        if not self.__str:
            # 源文本
            number = "3456789"
            srcLetter = "qwertyuipasdfghjkzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
            srcUpper = srcLetter.upper()
            if self.__type == 1:
                self.__str = number
            else:
                self.__str = srcLetter + srcUpper + number

        # 构造验证码
        self.__code = random.sample(self.__str, self.__length)

    def __createImage(self):
        '''创建画布'''
        bgColor = (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255))
        self.__img = Image.new('RGB', (self.__width, self.__heigth), bgColor)
        self.__draw = ImageDraw.Draw(self.__img)

    def __createNoise(self):
        '''画干扰点'''
        if not self.__inNoise:
            return
        font = ImageFont.truetype(self.__fontPatn, int(self.__fontSize / 1.5))
        for i in range(5):
            # 杂点颜色
            noiseColor = (random.randint(150, 200), random.randint(150, 200), random.randint(150, 200))
            putStr = random.sample(self.__str, 2)
            for j in range(2):
                # 绘杂点
                size = (random.randint(-10, self.__width), random.randint(-10, self.__heigth))
                self.__draw.text(size, putStr[j], font=font, fill=noiseColor)
        pass

    def __createCurve(self):
        '''画干扰线'''
        if not self.__inCurve:
            return
        x = y = 0

        # 计算曲线系数
        a = random.uniform(1, self.__heigth / 2)
        b = random.uniform(-self.__width / 4, self.__heigth / 4)
        f = random.uniform(-self.__heigth / 4, self.__heigth / 4)
        t = random.uniform(self.__heigth, self.__width * 2)
        xend = random.randint(self.__width / 2, self.__width * 2)
        w = (2 * math.pi) / t

        # 画曲线
        color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
        for x in range(xend):
            if w != 0:
                for k in range(int(self.__heigth / 10)):
                    y = a * math.sin(w * x + f) + b + self.__heigth / 2
                    i = int(self.__fontSize / 5)
                    while i > 0:
                        px = x + i
                        py = y + i + k
                        self.__draw.point((px, py), color)
                        i -= i

    def __printString(self):
        '''打印验证码字符串'''
        font = ImageFont.truetype(self.__fontPatn, self.__fontSize)
        x = 0
        # 打印字符到画板
        for i in range(self.__length):
            # 设置字体随机颜色
            color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
            # 计算座标
            x = random.uniform(self.__fontSize * i * 0.95, self.__fontSize * i * 1.1)
            y = self.__fontSize * random.uniform(0.3, 0.5)
            # 打印字符
            self.__draw.text((x, y), self.__code[i], font=font, fill=color)

# 生成验证码
def get_captcha():
    image, code = vieCode().GetCodeImage()
    code = ''.join(code).lower()
    out = BytesIO()
    session["code"] = code
    image.save(out, 'png')
    out.seek(0)
    resp = make_response(out.read())
    resp.content_type = 'image/png'
    return resp, code

app = Flask(__name__)
app.secret_key = 's3cr3t'
@app.route('/')
def index():
    response,code = get_captcha()
    print("code",code)
    return response

if __name__ == '__main__':
    app.run(debug=True)

 

 

 posted on 2024-10-17 17:56  boye169  阅读(58)  评论(0)    收藏  举报