zoukankan      html  css  js  c++  java
  • python---生成验证码图片

    工具插件verifycode.py中,记得使用时需要在路由根目录中引入文字资源文件

    # coding:utf8
    # __author:  Administrator
    # date:      2018/3/18 0018
    # /usr/bin/env python
    import random,os
    from PIL import Image,ImageDraw,ImageFont,ImageFilter
    
    class CreateCode:
        def __init__(self,size=(120,30),img_type="GIF",mode="RGB",bg_color=(255,255,255),
                     fg_color=(0,0,255),font_size=18,font_type="Monaco.ttf",length=4,
                     draw_lines=True,n_line = (1,2),draw_points=True,point_chance=2):
            '''
                @todo: 生成验证码图片
                @param size: 图片的大小,格式(宽,高),默认为(120, 30)
                @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
                @param mode: 图片模式,默认为RGB
                @param bg_color: 背景颜色,默认为白色
                @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
                @param font_size: 验证码字体大小
                @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
                @param length: 验证码字符个数
                @param draw_lines: 是否划干扰线
                @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
                @param draw_points: 是否画干扰点
                @param point_chance: 干扰点出现的概率,大小范围[0, 100]
                @return: [0]: PIL Image实例
                @return: [1]: 验证码图片中的字符串
                '''
            self.size=size
            self.img_type=img_type
            self.mode=mode
            self.bg_color=bg_color
            self.fg_color=fg_color
            self.font_size = font_size
            self.font_type =font_type
            self.length = length
            self.draw_lines =draw_lines
            self.point_chance = point_chance
            self.n_line=n_line
            self.draw_points=draw_points
            #执行初始化函数
            self.getAllChar()
            self.initPaint()
            self.get_chars()
    
        def initPaint(self):
            '''
            初始画布
            :return:
            '''
            self.width,self.height=self.size
            self.img = Image.new(self.mode,self.size,self.bg_color)
            self.draw = ImageDraw.Draw(self.img)#创建画笔
    
        def getAllChar(self):
            '''
            获取所有字符串
            :return:
            '''
            _letter_cases = "zxcvbnmasdfghjklqwertyuiop"
            _upper_cases = _letter_cases.upper()
            _numbers = ''.join(map(str, range(0, 9)))
            # 获取所有的字符
            self.init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
    
        def get_chars(self):
            '''生成给定长度的字符串,返回裂变格式'''
            return random.sample(self.init_chars,self.length)#从给定字符串中获取出随机字符
    
        def create_lines(self):
            '''绘制干扰线'''
            line_num = random.randint(*self.n_line)#从元组中获取线条数目
            for i in range(line_num):
                #起始点
                begin = (random.randint(0,self.size[0]),random.randint(0,self.size[1]))#在图片中随机位置
                end = (random.randint(0,self.size[0]),random.randint(0,self.size[1]))#在图片中随机位置
                self.draw.line([begin,end],fill=(0,0,0))
    
        def create_point(self):
            '''绘制干扰点'''
            chance = min(100,max(0,int(self.point_chance)))#大小限制在point_chance到100
            for w in range(self.width):
                for h in range(self.height):
                    tmp = random.randint(0,100)
                    if tmp > 100-chance:
                        self.draw.point((w,h),fill=(0,0,0))
    
        def create_strs(self):
            '''绘制验证码'''
            c_chars = self.get_chars()
            strs = ' %s '%' '.join(c_chars)
    
            font = ImageFont.truetype(self.font_type,self.font_size)
            font_width,font_height = font.getsize(strs)
    
            self.draw.text(((self.width-font_width)/3,(self.height-font_height)/3),strs,font=font,fill=self.fg_color)
    
            return ''.join(c_chars)
    
        def get_img(self):
            if self.draw_lines:
                self.create_lines()
            if self.draw_points:
                self.create_point()
            strs = self.create_strs()
            # 图形扭曲参数
            params = [1 - float(random.randint(1, 2)) / 100,
                      0,
                      0,
                      0,
                      1 - float(random.randint(1, 10)) / 100,
                      float(random.randint(1, 2)) / 500,
                      0.001,
                      float(random.randint(1, 2)) / 500
                      ]
            img = self.img.transform(self.size, Image.PERSPECTIVE, params)  # 创建扭曲
    
            img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)
    
            return img,strs
    
    
    if __name__=="__main__":
        img= CreateCode()
        image,code=img.get_img()
        print(code)

    在控制器中调用,并生成路由,在前端调用

    
    
    from backend.utils.verifycode import CreateCode

    class
    VerifyImgHandler(BaseRequestHandler): def get(self): Img = CreateCode(img_type="PNG") img,code = Img.get_img() self.session['code']=code #StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。 #BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes mstream = io.BytesIO() # 创建一个BytesIO临时保存生成图片数据 img.save(mstream,"PNG")#将返回的验证码图片数据,添加到BytesIO临时保存 self.write(mstream.getvalue())#从BytesIO临时保存,获取图片返回给img的 src= 进行显示

    路由添加:

    (r"/getcode",AccountController.VerifyImgHandler)

    前端代码:

        <div class="col-sm-4">
              <img style=" 100%;height: 100%" id="code" onclick="changeCode(this);" src="/getcode"/>
        </div>
        function changeCode(ths){
            var src =$(ths).attr("src")
            arr = src.split("?")
            src =arr[0]+'?'+Math.random()
            $(ths).attr("src",src)
        }

    函数模板使用:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import random
    from PIL import Image, ImageDraw, ImageFont, ImageFilter
    
    _letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
    _upper_cases = _letter_cases.upper()  # 大写字母
    _numbers = ''.join(map(str, range(3, 10)))  # 数字
    init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
    
    
    def create_validate_code(size=(120, 30),
                             chars=init_chars,
                             img_type="GIF",
                             mode="RGB",
                             bg_color=(255, 255, 255),
                             fg_color=(0, 0, 255),
                             font_size=18,
                             font_type="Monaco.ttf",
                             length=4,
                             draw_lines=True,
                             n_line=(1, 2),
                             draw_points=True,
                             point_chance=2):
        """
        @todo: 生成验证码图片
        @param size: 图片的大小,格式(宽,高),默认为(120, 30)
        @param chars: 允许的字符集合,格式字符串
        @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
        @param mode: 图片模式,默认为RGB
        @param bg_color: 背景颜色,默认为白色
        @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
        @param font_size: 验证码字体大小
        @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
        @param length: 验证码字符个数
        @param draw_lines: 是否划干扰线
        @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
        @param draw_points: 是否画干扰点
        @param point_chance: 干扰点出现的概率,大小范围[0, 100]
        @return: [0]: PIL Image实例
        @return: [1]: 验证码图片中的字符串
        """
    
        width, height = size  # 宽高
        # 创建图形
        img = Image.new(mode, size, bg_color)
        draw = ImageDraw.Draw(img)  # 创建画笔
    
        def get_chars():
            """生成给定长度的字符串,返回列表格式"""
            return random.sample(chars, length)
    
        def create_lines():
            """绘制干扰线"""
            line_num = random.randint(*n_line)  # 干扰线条数
    
            for i in range(line_num):
                # 起始点
                begin = (random.randint(0, size[0]), random.randint(0, size[1]))
                # 结束点
                end = (random.randint(0, size[0]), random.randint(0, size[1]))
                draw.line([begin, end], fill=(0, 0, 0))
    
        def create_points():
            """绘制干扰点"""
            chance = min(100, max(0, int(point_chance)))  # 大小限制在[0, 100]
    
            for w in range(width):
                for h in range(height):
                    tmp = random.randint(0, 100)
                    if tmp > 100 - chance:
                        draw.point((w, h), fill=(0, 0, 0))
    
        def create_strs():
            """绘制验证码字符"""
            c_chars = get_chars()
            strs = ' %s ' % ' '.join(c_chars)  # 每个字符前后以空格隔开
    
            font = ImageFont.truetype(font_type, font_size)
            font_width, font_height = font.getsize(strs)
    
            draw.text(((width - font_width) / 3, (height - font_height) / 3),
                      strs, font=font, fill=fg_color)
    
            return ''.join(c_chars)
    
        if draw_lines:
            create_lines()
        if draw_points:
            create_points()
        strs = create_strs()
    
        # 图形扭曲参数
        params = [1 - float(random.randint(1, 2)) / 100,
                  0,
                  0,
                  0,
                  1 - float(random.randint(1, 10)) / 100,
                  float(random.randint(1, 2)) / 500,
                  0.001,
                  float(random.randint(1, 2)) / 500
                  ]
        img = img.transform(size, Image.PERSPECTIVE, params)  # 创建扭曲
    
        img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)
    
        return img, strs
    验证码纯函数

    调用:

    def check_code(req):
        stream = BytesIO()  #获取内存块句柄,将数据保存在内存中
        img,code = create_validate_code()
        img.save(stream,'PNG')
        req.session['check_code']=code.lower()
    
        return HttpResponse(stream.getvalue())  #获取内存中的数据,返回给页面

    或者:

        f = open('1.png','wb')  #获取文件句柄,将数据保存在文件中
        img,code = create_validate_code()
        img.save(f,"PNG")   #将图片二进制数据写入文件中
  • 相关阅读:
    JavaScript 为字符串添加样式 【每日一段代码80】
    JavaScript replace()方法 【每日一段代码83】
    JavaScript for in 遍历数组 【每日一段代码89】
    JavaScript 创建用于对象的模板【每日一段代码78】
    html5 css3 新元素简单页面布局
    JavaScript Array() 数组 【每日一段代码88】
    JavaScript toUTCString() 方法 【每日一段代码86】
    位运算
    POJ 3259 Wormholes
    POJ 3169 Layout
  • 原文地址:https://www.cnblogs.com/ssyfj/p/8597448.html
Copyright © 2011-2022 走看看