精华内容
下载资源
问答
  • MyQR是一个能够生成自定义二维码的第三方库,你可以根据需要生成普通二维码、带图片的艺术二维码,也可以生成动态二维码。这篇文章主要介绍了Python使用MyQR制作专属动态彩色二维码,需要的朋友可以参考下
  • 相信朋友们都看过各种群里钓鱼的涩图二维码吧(手动滑稽),今天学了一下制作方式(myqr库的使用),在这里分享一下这个整活利器。 MyQR是一个能够生成自定义二维码的第三方库,可以根据需要生成普通二维码、带图片...
  • MyQR二维码生成.rar

    2019-09-27 22:28:35
    这个是用MyQR模块生成二维码,几行代码就可以生成二维码,简单方便
  • python是所有编程语言中模块最丰富的 生活中常见的二维码功能在使用python第三方库来生成十分容易 三个大矩形是定位图案,用于标记二维码的大小...pip install myqr #操作简单,功能强大 QRCode 多种自定义方法 imp
  • 现在介绍一个可以生成动态二维码的库(myqr) 效果如图: 第一步要安装myqr库 在cmd中直接用pip安装 pip install myqr 第二步 from MyQR import myqr import os version, level, qr_name = myqr.run( words=...
  • myqr

    2020-06-04 18:26:09
    myqr 安装 pip install myqr 启动 在python解释器中 from MyQR import myqr import os version, level, qr_name=myqr.run( words, version=1, level='H', picture=None, colorized=False, contrast=1.0...

    myqr

    1. 安装

      pip install myqr

    2. 启动

      • 在python解释器中

        from MyQR import myqr
        import os
        
        version, level, qr_name=myqr.run(
        	words,
        	version=1,
        	level='H',
        	picture=None,
        	colorized=False,
        	contrast=1.0,
        	brightness=1.0,
        	save_name=None,
        	save_dir=os.getcwd()
        )
        
      • 在terminal中(可能需要将myqr的路径添加到PATH中,修改.zshrc or .bashrc文件)

        # summary
        myqr 	Words
        		[-v {1,2,3,...,40}]
        		[-l {L,M,Q,H}]
                [-n output-filename]
        		[-d output-directory]
        		[-p picture_file]
        		[-c]
        		[-con contrast]
        		[-bri brightness]
        		
        		
        		
        # examples
        myqr https://www.baidu.com
        myqr https://www.baidu.com -v 2 # version [1-40]
        myqr https://www.baidu.com -v 3 -l H # level 'L, M, Q, H'
        myqr https://www.baidu.com -n baidu.jpg -d /tmp # save_name, save_dir
        myqr https://www.baidu.com -p art.jpg -n baidu.png -d /tmp # -p
        myqr https://www.baidu.com -p art.jpg -n baidu.png -d /tmp -c # colorized=True
        myqr https://www.baidu.com -p art.jpg -n baidu.png -d /tmp -c -con 1.0 -bri 1.0 # contrast=1.0 brightness=1.0
        myqr hello -p hello.gif -n hello.gif -d /tmp -c # .gif makes the QR animated
        

        原文请参考:https://github.com/sylnsfar/qrcode

    展开全文
  • MyQR代码阅读

    千次阅读 2019-12-12 00:52:40
    MyQR 代码地址 github

    看了一下MyQR的源代码,查了一些资料有些原理还是没看懂,把看懂的部分记录一下。

    MyQR 代码地址

    github链接

    QR二维码编码原理

    QR码的特点

    • 高速读取
    • 高容量、高密度
    • 支持纠错处理
    • 结构化
    • 扩展能力(一个QR码可以分解成多个QR码,反之,也可以将多个QR码的数据组合到一个QR码中来。)

    QR码结构

    在这里插入图片描述

    • 位置探测图形、位置探测图形分隔符、定位图形:用于对二维码的定位,对每个QR码来说,位置都是固定存在的,只是大小规格会有所差异。
    • 校正图形:规格确定,校正图形的数量和位置也就确定了。
    • 格式信息:表示改二维码的纠错级别,分为L、M、Q、H
    • 版本信息:即二维码的规格,QR码符号共有40种规格的矩阵(一般为黑白色),从21x21(版本1),到177x177(版本40),每一版本符号比前一版本 每边增加4个模块。
    • 数据和纠错码字:实际保存的二维码信息,和纠错码字(用于修正二维码损坏带来的错误)。

    简要的编码过程

    1. 数据分析
      确定编码的字符类型,按相应的字符集转换成符号字符; 选择纠错等级,在规格一定的条件下,纠错等级越高其真实数据的容量越小。
    2. 数据编码
      将数据字符转换为位流,每8位一个码字,整体构成一个数据的码字序列。其实知道这个数据码字序列就知道了二维码的数据内容。
      容量:
    格式容量
    数字最多7089字符
    字母最多4296字符
    二进制数(8 bit)最多2953字节
    日文汉字/片假名最多1817字符(采用Shift JIS)
    中文汉字最多984字符(采用UTF-8)
    中文汉字最多1800字符(采用BIG5)

    模式编码:

    模式指示符
    ECI0111
    数字0001
    字母数字0010
    8位字节0100
    日本汉字1000
    中文汉字1101
    结构链接0011
    FNCI0101(第一位置)1001(第二位置)
    终止符(信息结尾)0000
    1. 纠错编码
      按需要将上面的码字序列分块,并根据纠错等级和分块的码字,产生纠错码字,并把纠错码字加入到数据码字序列后面,成为一个新的序列。
    2. 构造最终数据信息
      按规定把数据分块,然后对每一块进行计算,得出相应的纠错码字区块,把纠错码字区块 按顺序构成一个序列,添加到原先的数据码字序列后面。
    3. 构造矩阵
      将探测图形、分隔符、定位图形、校正图形和码字模块放入矩阵中。
      在这里插入图片描述
    4. 掩摸
      将掩摸图形用于符号的编码区域,使得二维码图形中的深色和浅色(黑色和白色)区域能够比率最优的分布。
    5. 格式和版本信息
      生成格式和版本信息放入相应区域内。

    数据内容编码

    1、数字模式下的编码

    数据被限制为3个数字一段,分成若干段。如:“123456” 将分成"123" 和 “456”,分别被编码成10bit的二进制数。“123”的10bit二进制表示法为:0001111011,实际上就是二进制的123。
    当数据的长度不足3个数字时,如果只有1个数字则用4bit,如果有2个数字就用7个bit来表示。
    如:“9876"被分成"987"和"6"两段,因此被表示为"1111011011 0110”。

    2、混合字符模式下的编码

    字符对照表:

    00A10K20U30+40
    11B11L21V31-41
    22C12M22W32.42
    33D13N23X33/43
    44E14O24Y34:44
    55F15P25Z35
    66G16Q26[sp]36
    77H17R27$37
    88I18S28%38
    99j19T29*39

    源码被分成两个字符一段,如下所示,每段的第一个字符乘上45,再用第二个数字相加。因此每段变成了11bit的2进制码,如果字符个数只有1个,则用6bit表示。

    示例:

    “AB”“CD”“E1”“23”
    45*10+1145*12+1345*14+145*2+3
    46155363193
    001000000100000111001101010001010010100111011100001011101

    3、8bit字节数据不经编码转换直接保存。

    4、编码终止符(Terminator)

    如果编码后的字符长度不足当前版本和纠错级别所存储的容量,则在后续补"0000",如果容量已满则无需添加终止符。

    5、编成8bit码字

    按8bit一组,形成码字(code words)。
    如果编码后的数据不足版本及纠错级别的最大容量,则在尾部补充 “11101100” 和 “00010001”,直到全部填满。

    文件代码解析

    文件结构

    │  myqr.py
    │  
    └─MyQR
        │  myqr.py		# 使用接口
        │  terminal.py	# 参数设置(命令行、代码)
        │  __init__.py
        │  
        └─mylibs
                constant.py		# 数据
                data.py			# 数据编码
                draw.py			# 生成二维码
                ECC.py			# 纠错编码
                matrix.py		# QR矩阵
                structure.py	# 构造最终数据信息
                theqrmodule.py	# 逻辑函数
                __init__.py
    

    myqr.py

    # -*- coding: utf-8 -*-
    
    # To be used just when MyQR is not installed
    
    from MyQR.terminal import main
    
    main()
    

    导入MyQR模块 运行terminal.main

    terminal.py

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    from MyQR.myqr import run
    import os
    
    def main():
        import argparse	# 命令行参数模块
        argparser = argparse.ArgumentParser()
        argparser.add_argument('Words', help = 'The words to produce you QR-code picture, like a URL or a sentence. Please read the README file for the supported characters.')
        argparser.add_argument('-v', '--version', type = int, choices = range(1,41), default = 1, help = 'The version means the length of a side of the QR-Code picture. From little size to large is 1 to 40.')
        argparser.add_argument('-l', '--level', choices = list('LMQH'), default = 'H', help = 'Use this argument to choose an Error-Correction-Level: L(Low), M(Medium) or Q(Quartile), H(High). Otherwise, just use the default one: H')
        argparser.add_argument('-p', '--picture', help = 'the picture  e.g. example.jpg')
        argparser.add_argument('-c', '--colorized', action = 'store_true', help = "Produce a colorized QR-Code with your picture. Just works when there is a correct '-p' or '--picture'.")
        argparser.add_argument('-con', '--contrast', type = float, default = 1.0, help = 'A floating point value controlling the enhancement of contrast. Factor 1.0 always returns a copy of the original image, lower factors mean less color (brightness, contrast, etc), and higher values more. There are no restrictions on this value. Default: 1.0')
        argparser.add_argument('-bri', '--brightness', type = float, default = 1.0, help = 'A floating point value controlling the enhancement of brightness. Factor 1.0 always returns a copy of the original image, lower factors mean less color (brightness, contrast, etc), and higher values more. There are no restrictions on this value. Default: 1.0')
        argparser.add_argument('-n', '--name', help = "The filename of output tailed with one of {'.jpg', '.png', '.bmp', '.gif'}. eg. exampl.png")
        argparser.add_argument('-d', '--directory', default = os.getcwd(), help = 'The directory of output.')
        args = argparser.parse_args()
        
        if args.picture and args.picture[-4:]=='.gif':	# 如果是gif图片则解析的时间较多让用户稍作等待
            print('It may take a while, please wait for minutes...')
        
        try:
            ver, ecl, qr_name = run(
                args.Words,
                args.version,
                args.level,
                args.picture,
                args.colorized,
                args.contrast,
                args.brightness,
                args.name,
                args.directory
                )   
            print('Succeed! \nCheck out your', str(ver) + '-' + str(ecl), 'QR-code:', qr_name)
        except:
            raise	# 引起异常
    

    可以看出MyQR运行的主要函数就是MyQR.myqr.run,可以使用命令行的形式,也可以直接调用函数。具体参数意义在二维码生成的文章里面已经说过了。

    MyQR.myqr

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import os
    from MyQR.mylibs import theqrmodule
    from PIL import Image
       
    # 必填参数
    #   words: str
    #
    # 可选参数
    #   version: int, from 1 to 40
    #   level: str, just one of ('L','M','Q','H')
    #   picutre: str, a filename of a image
    #   colorized: bool
    #   constrast: float
    #   brightness: float
    #   save_name: str, the output filename like 'example.png'
    #   save_dir: str, the output directory
    #
    # See [https://github.com/sylnsfar/qrcode] for more details!
    def run(words, version=1, level='H', picture=None, colorized=False, contrast=1.0, brightness=1.0, save_name=None, save_dir=os.getcwd()):
    
        # 支持的字符
        supported_chars = r"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ··,.:;+-*/\~!@#$%^&`'=<>[]()?_{}|"
    
        # 检查参数是否正确
        # 看样子这好像不支持输入中文啊
        if not isinstance(words, str) or any(i not in supported_chars for i in words):
            raise ValueError('Wrong words! Make sure the characters are supported!')
        # QR码的最大容量取决于选择的版本、纠错级别和编码模式。这里支持40个版本。
        if not isinstance(version, int) or version not in range(1, 41):
            raise ValueError('Wrong version! Please choose a int-type value from 1 to 40!')
        # 纠错能力 L:约%7 M:约%15 Q:约%25 H:约%30
        if not isinstance(level, str) or len(level)>1 or level not in 'LMQH':
            raise ValueError("Wrong level! Please choose a str-type level from {'L','M','Q','H'}!")
        # 背景图片只支持jpg, png, bmp, gif
        if picture:
            if not isinstance(picture, str) or not os.path.isfile(picture) or picture[-4:] not in ('.jpg','.png','.bmp','.gif'):
                raise ValueError("Wrong picture! Input a filename that exists and be tailed with one of {'.jpg', '.png', '.bmp', '.gif'}!")
            # gif图片只能导出gif图片
            if picture[-4:] == '.gif' and save_name and save_name[-4:] != '.gif':
                raise ValueError('Wrong save_name! If the picuter is .gif format, the output filename should be .gif format, too!')
            if not isinstance(colorized, bool):
                raise ValueError('Wrong colorized! Input a bool-type value!')
            if not isinstance(contrast, float):
                raise ValueError('Wrong contrast! Input a float-type value!')
            if not isinstance(brightness, float):
                raise ValueError('Wrong brightness! Input a float-type value!')
        # 导出文件格式只支持jpg, png, bmp, gif
        if save_name and (not isinstance(save_name, str) or save_name[-4:] not in ('.jpg','.png','.bmp','.gif')):
            raise ValueError("Wrong save_name! Input a filename tailed with one of {'.jpg', '.png', '.bmp', '.gif'}!")
        # 保存文件夹一定要存在(感觉不存在也可以创建一下啊)
        if not os.path.isdir(save_dir):
            raise ValueError('Wrong save_dir! Input a existing-directory!')
        
        # 合并图片(背景和二维码)
        def combine(ver, qr_name, bg_name, colorized, contrast, brightness, save_dir, save_name=None):
            from MyQR.mylibs.constant import alig_location
            from PIL import ImageEnhance, ImageFilter
            
            qr = Image.open(qr_name)    # 二维码
            qr = qr.convert('RGBA') if colorized else qr    # 二维码是否着色
            
            bg0 = Image.open(bg_name).convert('RGBA')   # 背景图片(4x8位像素,带透明度掩模的真彩色)
            bg0 = ImageEnhance.Contrast(bg0).enhance(contrast)  # 调节对比度
            bg0 = ImageEnhance.Brightness(bg0).enhance(brightness)  # 调节亮度
    
            # 调整背景图片大小
            if bg0.size[0] < bg0.size[1]:
                bg0 = bg0.resize((qr.size[0]-24, (qr.size[0]-24)*int(bg0.size[1]/bg0.size[0])))
            else:
                bg0 = bg0.resize(((qr.size[1]-24)*int(bg0.size[0]/bg0.size[1]), qr.size[1]-24))    
    
            # convert('1')(1位像素,黑白,每字节一个像素存储)
            bg = bg0 if colorized else bg0.convert('1')
            
            # 校准模式
            aligs = []
            if ver > 1:
                aloc = alig_location[ver-2]
                for a in range(len(aloc)):
                    for b in range(len(aloc)):
                        if not ((a==b==0) or (a==len(aloc)-1 and b==0) or (a==0 and b==len(aloc)-1)):
                            for i in range(3*(aloc[a]-2), 3*(aloc[a]+3)):
                                for j in range(3*(aloc[b]-2), 3*(aloc[b]+3)):
                                    aligs.append((i,j))
    
            # 将新加的图片覆盖原有的二维码图片,生成新的图片并保存。
            for i in range(qr.size[0]-24):
                for j in range(qr.size[1]-24):
                    if not ((i in (18,19,20)) or (j in (18,19,20)) or (i<24 and j<24) or (i<24 and j>qr.size[1]-49) or (i>qr.size[0]-49 and j<24) or ((i,j) in aligs) or (i%3==1 and j%3==1) or (bg0.getpixel((i,j))[3]==0)):
                        qr.putpixel((i+12,j+12), bg.getpixel((i,j)))
            
            qr_name = os.path.join(save_dir, os.path.splitext(os.path.basename(bg_name))[0] + '_qrcode.png') if not save_name else os.path.join(save_dir, save_name)
            qr.resize((qr.size[0]*3, qr.size[1]*3)).save(qr_name)
            return qr_name
    
        # 临时文件夹暂存图片
        tempdir = os.path.join(os.path.expanduser('~'), '.myqr')
        
        try:
            # 创建临时文件夹
            if not os.path.exists(tempdir):
                os.makedirs(tempdir)
    
            # 得到一个qrcode图片(每个模块3*3 pixels)
            ver, qr_name = theqrmodule.get_qrcode(version, level, words, tempdir)
    
            if picture and picture[-4:]=='.gif':
                import imageio
                
                im = Image.open(picture)
                duration = im.info.get('duration', 0)   # 获得gif持续时间
                # 获得gif的所有帧0.png 1.png 2.png...
                im.save(os.path.join(tempdir, '0.png'))
                while True:
                    try:
                        seq = im.tell()
                        im.seek(seq + 1)
                        im.save(os.path.join(tempdir, '%s.png' %(seq+1)))
                    except EOFError:
                        break
                
                # 组合每帧图片和二维码
                imsname = []
                for s in range(seq + 1):
                    bg_name = os.path.join(tempdir, '%s.png' % s)
                    imsname.append(combine(ver, qr_name, bg_name, colorized, contrast, brightness, tempdir))
                
                # 把合成的帧组合成gif
                ims = [imageio.imread(pic) for pic in imsname]
                qr_name = os.path.join(save_dir, os.path.splitext(os.path.basename(picture))[0] + '_qrcode.gif') if not save_name else os.path.join(save_dir, save_name)
                imageio.mimwrite(qr_name, ims, '.gif', **{ 'duration': duration/1000 })
            elif picture:   # 有背景图片就需要合并背景和二维码
                qr_name = combine(ver, qr_name, picture, colorized, contrast, brightness, save_dir, save_name)
            elif qr_name:
                qr = Image.open(qr_name)
                # 没有输入保存名字就使用默认名字qr_name变量(qrcode)
                qr_name = os.path.join(save_dir, os.path.basename(qr_name)) if not save_name else os.path.join(save_dir, save_name)
                qr.resize((qr.size[0]*3, qr.size[1]*3)).save(qr_name)
            
            # 返回QR码版本 纠错能力 导出文件名字
            return ver, level, qr_name
            
        except:
            raise
        finally:
            # 销毁临时文件夹
            import shutil
            if os.path.exists(tempdir):
                shutil.rmtree(tempdir)
    

    其中最重要的就是theqrmodule.get_qrcode得到原始二维码。
    其他内容主要就是把背景图片加入二维码里面(qr.putpixel((i+12,j+12), bg.getpixel((i,j))))

    theqrmodule.py

    # -*- coding: utf-8 -*-
    
    from MyQR.mylibs import data, ECC, structure, matrix, draw
    
    # ver: Version from 1 to 40
    # ecl: Error Correction Level (L,M,Q,H)
    # get a qrcode picture of 3*3 pixels per module
    def get_qrcode(ver, ecl, str, save_place):
        # Data Coding
        # 将数据字符转换为位流,每8位一个码字,整体构成一个数据的码字序列。
        ver, data_codewords = data.encode(ver, ecl, str)
    
        # Error Correction Coding
        # 按需要将上面的码字序列分块,并根据纠错等级和分块的码字,产生纠错码字,并把纠错码字加入到数据码字序列后面,成为一个新的序列。
        ecc = ECC.encode(ver, ecl, data_codewords)
        
        # Structure final bits
        # 构造最终数据信息
        final_bits = structure.structure_final_bits(ver, ecl, data_codewords, ecc)
        
        # Get the QR Matrix
        # 得到二维码的矩阵
        qrmatrix = matrix.get_qrmatrix(ver, ecl, final_bits)
            
        # Draw the picture and Save it, then return the real ver and the absolute name
        # 生成二维码
        return ver, draw.draw_qrcode(save_place, qrmatrix)
    
    

    这是一个二维码生成的逻辑

    constant.py

    # -*- coding: utf-8 -*-
    """
    ***** for data.py *******
    """
    # character capacities
    # {level1: [version1(mode1,mode2,mode3,mode4), version2(..,..,..,..), ...],
    #   level2: [version1(mode1,mode2,mode3,mode4), version2(..,..,..,..),...],
    #   ...}
    # mode1:纯数字(每三个为一组压缩成10bit)
    # mode2:字母数字混合字符(每两个为一组,压缩成11bit)
    # mode3:8bit字节数据(无压缩直接保存)
    # mode4:多字节字符(每一个字符被压缩成13bit)
    char_cap = {
            'L': [(41, 25, 17, 10), (77, 47, 32, 20), (127, 77, 53, 32), (187, 114, 78, 48), (255, 154, 106, 65), (322, 195, 134, 82), (370, 224, 154, 95), (461, 279, 192, 118), (552, 335, 230, 141), (652, 395, 271, 167), (772, 468, 321, 198), (883, 535, 367, 226), (1022, 619, 425, 262), (1101, 667, 458, 282), (1250, 758, 520, 320), (1408, 854, 586, 361), (1548, 938, 644, 397), (1725, 1046, 718, 442), (1903, 1153, 792, 488), (2061, 1249, 858, 528), (2232, 1352, 929, 572), (2409, 1460, 1003, 618), (2620, 1588, 1091, 672), (2812, 1704, 1171, 721), (3057, 1853, 1273, 784), (3283, 1990, 1367, 842), (3517, 2132, 1465, 902), (3669, 2223, 1528, 940), (3909, 2369, 1628, 1002), (4158, 2520, 1732, 1066), (4417, 2677, 1840, 1132), (4686, 2840, 1952, 1201), (4965, 3009, 2068, 1273), (5253, 3183, 2188, 1347), (5529, 3351, 2303, 1417), (5836, 3537, 2431, 1496), (6153, 3729, 2563, 1577), (6479, 3927, 2699, 1661), (6743, 4087, 2809, 1729), (7089, 4296, 2953, 1817)],
            'M': [(34, 20, 14, 8), (63, 38, 26, 16), (101, 61, 42, 26), (149, 90, 62, 38), (202, 122, 84, 52), (255, 154, 106, 65), (293, 178, 122, 75), (365, 221, 152, 93), (432, 262, 180, 111), (513, 311, 213, 131), (604, 366, 251, 155), (691, 419, 287, 177), (796, 483, 331, 204), (871, 528, 362, 223), (991, 600, 412, 254), (1082, 656, 450, 277), (1212, 734, 504, 310), (1346, 816, 560, 345), (1500, 909, 624, 384), (1600, 970, 666, 410), (1708, 1035, 711, 438), (1872, 1134, 779, 480), (2059, 1248, 857, 528), (2188, 1326, 911, 561), (2395, 1451, 997, 614), (2544, 1542, 1059, 652), (2701, 1637, 1125, 692), (2857, 1732, 1190, 732), (3035, 1839, 1264, 778), (3289, 1994, 1370, 843), (3486, 2113, 1452, 894), (3693, 2238, 1538, 947), (3909, 2369, 1628, 1002), (4134, 2506, 1722, 1060), (4343, 2632, 1809, 1113), (4588, 2780, 1911, 1176), (4775, 2894, 1989, 1224), (5039, 3054, 2099, 1292), (5313, 3220, 2213, 1362), (5596, 3391, 2331, 1435)],
            'Q': [(27, 16, 11, 7), (48, 29, 20, 12), (77, 47, 32, 20), (111, 67, 46, 28), (144, 87, 60, 37), (178, 108, 74, 45), (207, 125, 86, 53), (259, 157, 108, 66), (312, 189, 130, 80), (364, 221, 151, 93), (427, 259, 177, 109), (489, 296, 203, 125), (580, 352, 241, 149), (621, 376, 258, 159), (703, 426, 292, 180), (775, 470, 322, 198), (876, 531, 364, 224), (948, 574, 394, 243), (1063, 644, 442, 272), (1159, 702, 482, 297), (1224, 742, 509, 314), (1358, 823, 565, 348), (1468, 890, 611, 376), (1588, 963, 661, 407), (1718, 1041, 715, 440), (1804, 1094, 751, 462), (1933, 1172, 805, 496), (2085, 1263, 868, 534), (2181, 1322, 908, 559), (2358, 1429, 982, 604), (2473, 1499, 1030, 634), (2670, 1618, 1112, 684), (2805, 1700, 1168, 719), (2949, 1787, 1228, 756), (3081, 1867, 1283, 790), (3244, 1966, 1351, 832), (3417, 2071, 1423, 876), (3599, 2181, 1499, 923), (3791, 2298, 1579, 972), (3993, 2420, 1663, 1024)],
            'H': [(17, 10, 7, 4), (34, 20, 14, 8), (58, 35, 24, 15), (82, 50, 34, 21), (106, 64, 44, 27), (139, 84, 58, 36), (154, 93, 64, 39), (202, 122, 84, 52), (235, 143, 98, 60), (288, 174, 119, 74), (331, 200, 137, 85), (374, 227, 155, 96), (427, 259, 177, 109), (468, 283, 194, 120), (530, 321, 220, 136), (602, 365, 250, 154), (674, 408, 280, 173), (746, 452, 310, 191), (813, 493, 338, 208), (919, 557, 382, 235), (969, 587, 403, 248), (1056, 640, 439, 270), (1108, 672, 461, 284), (1228, 744, 511, 315), (1286, 779, 535, 330), (1425, 864, 593, 365), (1501, 910, 625, 385), (1581, 958, 658, 405), (1677, 1016, 698, 430), (1782, 1080, 742, 457), (1897, 1150, 790, 486), (2022, 1226, 842, 518), (2157, 1307, 898, 553), (2301, 1394, 958, 590), (2361, 1431, 983, 605), (2524, 1530, 1051, 647), (2625, 1591, 1093, 673), (2735, 1658, 1139, 701), (2927, 1774, 1219, 750), (3057, 1852, 1273, 784)]
            }
    
    # numeric:数字 alphanumeric:字母数字 byte:字节 kanji:汉字
    mindex = {'numeric':0, 'alphanumeric':1, 'byte':2, 'kanji':3}
    
    # [
    # version1[level1,level2,level3,level4], 
    # version2[..,..,..,..],
    # ...
    #   ]
    # 数据码字计数(count of data code words)
    required_bytes = [
            [19, 16, 13, 9], [34, 28, 22, 16], [55, 44, 34, 26], [80, 64, 48, 36], [108, 86, 62, 46], [136, 108, 76, 60], [156, 124, 88, 66], [194, 154, 110, 86], [232, 182, 132, 100], [274, 216, 154, 122], [324, 254, 180, 140], [370, 290, 206, 158], [428, 334, 244, 180], [461, 365, 261, 197], [523, 415, 295, 223], [589, 453, 325, 253], [647, 507, 367, 283], [721, 563, 397, 313], [795, 627, 445, 341], [861, 669, 485, 385], [932, 714, 512, 406], [1006, 782, 568, 442], [1094, 860, 614, 464], [1174, 914, 664, 514], [1276, 1000, 718, 538], [1370, 1062, 754, 596], [1468, 1128, 808, 628], [1531, 1193, 871, 661], [1631, 1267, 911, 701], [1735, 1373, 985, 745], [1843, 1455, 1033, 793], [1955, 1541, 1115, 845], [2071, 1631, 1171, 901], [2191, 1725, 1231, 961], [2306, 1812, 1286, 986], [2434, 1914, 1354, 1054], [2566, 1992, 1426, 1096], [2702, 2102, 1502, 1142], [2812, 2216, 1582, 1222], [2956, 2334, 1666, 1276]
            ]
    
    # 支持的数字
    num_list = '0123456789'
    # 支持的字母字符
    alphanum_list = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'
    
    # [
    # version1[
    #       level1(num_of_group_1_blocks, DC_per_group_1_block, num_of_group_2_blocks, DC_per_group_2_block),
    #       level2(..,..,..,..),
    #       level3(..,..,..,..),
    #       level4(..,..,..,..)
    #       ], 
    # version2[level1(..), level2(..), level3(..), level4(..)],
    # ...
    #   ]
    # 码元分组
    grouping_list = [
        [(1, 19, 0, 0), (1, 16, 0, 0), (1, 13, 0, 0), (1, 9, 0, 0)], [(1, 34, 0, 0), (1, 28, 0, 0), (1, 22, 0, 0), (1, 16, 0, 0)], [(1, 55, 0, 0), (1, 44, 0, 0), (2, 17, 0, 0), (2, 13, 0, 0)], [(1, 80, 0, 0), (2, 32, 0, 0), (2, 24, 0, 0), (4, 9, 0, 0)], [(1, 108, 0, 0), (2, 43, 0, 0), (2, 15, 2, 16), (2, 11, 2, 12)], [(2, 68, 0, 0), (4, 27, 0, 0), (4, 19, 0, 0), (4, 15, 0, 0)], [(2, 78, 0, 0), (4, 31, 0, 0), (2, 14, 4, 15), (4, 13, 1, 14)], [(2, 97, 0, 0), (2, 38, 2, 39), (4, 18, 2, 19), (4, 14, 2, 15)], [(2, 116, 0, 0), (3, 36, 2, 37), (4, 16, 4, 17), (4, 12, 4, 13)], [(2, 68, 2, 69), (4, 43, 1, 44), (6, 19, 2, 20), (6, 15, 2, 16)], [(4, 81, 0, 0), (1, 50, 4, 51), (4, 22, 4, 23), (3, 12, 8, 13)], [(2, 92, 2, 93), (6, 36, 2, 37), (4, 20, 6, 21), (7, 14, 4, 15)], [(4, 107, 0, 0), (8, 37, 1, 38), (8, 20, 4, 21), (12, 11, 4, 12)], [(3, 115, 1, 116), (4, 40, 5, 41), (11, 16, 5, 17), (11, 12, 5, 13)], [(5, 87, 1, 88), (5, 41, 5, 42), (5, 24, 7, 25), (11, 12, 7, 13)], [(5, 98, 1, 99), (7, 45, 3, 46), (15, 19, 2, 20), (3, 15, 13, 16)], [(1, 107, 5, 108), (10, 46, 1, 47), (1, 22, 15, 23), (2, 14, 17, 15)], [(5, 120, 1, 121), (9, 43, 4, 44), (17, 22, 1, 23), (2, 14, 19, 15)], [(3, 113, 4, 114), (3, 44, 11, 45), (17, 21, 4, 22), (9, 13, 16, 14)], [(3, 107, 5, 108), (3, 41, 13, 42), (15, 24, 5, 25), (15, 15, 10, 16)], [(4, 116, 4, 117), (17, 42, 0, 0), (17, 22, 6, 23), (19, 16, 6, 17)], [(2, 111, 7, 112), (17, 46, 0, 0), (7, 24, 16, 25), (34, 13, 0, 0)], [(4, 121, 5, 122), (4, 47, 14, 48), (11, 24, 14, 25), (16, 15, 14, 16)], [(6, 117, 4, 118), (6, 45, 14, 46), (11, 24, 16, 25), (30, 16, 2, 17)], [(8, 106, 4, 107), (8, 47, 13, 48), (7, 24, 22, 25), (22, 15, 13, 16)], [(10, 114, 2, 115), (19, 46, 4, 47), (28, 22, 6, 23), (33, 16, 4, 17)], [(8, 122, 4, 123), (22, 45, 3, 46), (8, 23, 26, 24), (12, 15, 28, 16)], [(3, 117, 10, 118), (3, 45, 23, 46), (4, 24, 31, 25), (11, 15, 31, 16)], [(7, 116, 7, 117), (21, 45, 7, 46), (1, 23, 37, 24), (19, 15, 26, 16)], [(5, 115, 10, 116), (19, 47, 10, 48), (15, 24, 25, 25), (23, 15, 25, 16)], [(13, 115, 3, 116), (2, 46, 29, 47), (42, 24, 1, 25), (23, 15, 28, 16)], [(17, 115, 0, 0), (10, 46, 23, 47), (10, 24, 35, 25), (19, 15, 35, 16)], [(17, 115, 1, 116), (14, 46, 21, 47), (29, 24, 19, 25), (11, 15, 46, 16)], [(13, 115, 6, 116), (14, 46, 23, 47), (44, 24, 7, 25), (59, 16, 1, 17)], [(12, 121, 7, 122), (12, 47, 26, 48), (39, 24, 14, 25), (22, 15, 41, 16)], [(6, 121, 14, 122), (6, 47, 34, 48), (46, 24, 10, 25), (2, 15, 64, 16)], [(17, 122, 4, 123), (29, 46, 14, 47), (49, 24, 10, 25), (24, 15, 46, 16)], [(4, 122, 18, 123), (13, 46, 32, 47), (48, 24, 14, 25), (42, 15, 32, 16)], [(20, 117, 4, 118), (40, 47, 7, 48), (43, 24, 22, 25), (10, 15, 67, 16)], [(19, 118, 6, 119), (18, 47, 31, 48), (34, 24, 34, 25), (20, 15, 61, 16)]
        ]
    
    # 模式标识符:对于不同的模式,都有对应的模式标识符来帮助解码程序进行匹配
    mode_indicator = {'numeric': '0001', 'alphanumeric': '0010', 'byte': '0100', 'kanji': '1000'}
    
    """
    ******  for ECC.py  *******
    """
    #GP: Generator Polynomial, MP: Message Polynomial
    # GP:生成多项式 MP:消息多项式
    GP_list = {
            7: [0, 87, 229, 146, 149, 238, 102, 21],
            10: [0, 251, 67, 46, 61, 118, 70, 64, 94, 32, 45],
            13: [0, 74, 152, 176, 100, 86, 100, 106, 104, 130, 218, 206, 140, 78],
            15: [0, 8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140, 124, 5, 99, 105],
            16: [0, 120, 104, 107, 109, 102, 161, 76, 3, 91, 191, 147, 169, 182, 194, 225, 120],
            17: [0, 43, 139, 206, 78, 43, 239, 123, 206, 214, 147, 24, 99, 150, 39, 243, 163, 136],
            18: [0, 215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, 148, 252, 179, 5, 98, 96, 153],
            20: [0, 17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221, 225, 83, 239, 156, 164, 212, 212, 188, 190],
            22: [0, 210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200, 74, 8, 172, 98, 80, 219, 134, 160, 105, 165, 231],
            24: [0, 229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169, 152, 192, 226, 228, 218, 111, 0, 117, 232, 87, 96, 227, 21],
            26: [0, 173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111, 28, 165, 53, 161, 21, 245, 142, 13, 102, 48, 227, 153, 145, 218, 70],
            28: [0, 168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195, 147, 205, 27, 232, 201, 21, 43, 245, 87, 42, 195, 212, 119, 242, 37, 9, 123],
            30: [0, 41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110, 86, 239, 96, 222, 125, 42, 173, 226, 193, 224, 130, 156, 37, 251, 216, 238, 40, 192, 180]
            }
    
    # Error Correction Codewords per block
    # [version1(level1,level2,level3,level4),
    #  version2(..,..,..,..),
    #   ....]
    # 每个块的错误纠正码字
    ecc_num_per_block = [
        (7, 10, 13, 17), (10, 16, 22, 28), (15, 26, 18, 22), (20, 18, 26, 16), (26, 24, 18, 22), (18, 16, 24, 28), (20, 18, 18, 26), (24, 22, 22, 26), (30, 22, 20, 24), (18, 26, 24, 28), (20, 30, 28, 24), (24, 22, 26, 28), (26, 22, 24, 22), (30, 24, 20, 24), (22, 24, 30, 24), (24, 28, 24, 30), (28, 28, 28, 28), (30, 26, 28, 28), (28, 26, 26, 26), (28, 26, 30, 28), (28, 26, 28, 30), (28, 28, 30, 24), (30, 28, 30, 30), (30, 28, 30, 30), (26, 28, 30, 30), (28, 28, 28, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30), (30, 28, 30, 30)
        ]
            
    
    # powers of 2 list  
    po2 = [
        1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1
        ]
        
    # log list
    log = [
        None, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175
        ]
    
    """
    ******  for data.py + ECC.py + structure.py + matrix.py  *******
    """
    # 模式标识符对应的简写
    lindex = {'L':0, 'M':1, 'Q':2, 'H':3}
        
    """
    ******  for structure.py  *******
    """    
    # 剩余部分需要的位数
    required_remainder_bits = (0,7,7,7,7,7,0,0,0,0,0,0,0,3,3,3,3,3,3,3,4,4,4,4,4,4,4,3,3,3,3,3,3,3,0,0,0,0,0,0)
    
    # [
    # version1[
    #       level1(num_of_group_1_blocks, DC_per_group_1_block, num_of_group_2_blocks, DC_per_group_2_block),
    #       level2(..,..,..,..),
    #       level3(..,..,..,..),
    #       level4(..,..,..,..)
    #       ], 
    # version2[level1(..), level2(..), level3(..), level4(..)],
    # ...
    #   ]
    # 码元分组
    grouping_list = [
        [(1, 19, 0, 0), (1, 16, 0, 0), (1, 13, 0, 0), (1, 9, 0, 0)], [(1, 34, 0, 0), (1, 28, 0, 0), (1, 22, 0, 0), (1, 16, 0, 0)], [(1, 55, 0, 0), (1, 44, 0, 0), (2, 17, 0, 0), (2, 13, 0, 0)], [(1, 80, 0, 0), (2, 32, 0, 0), (2, 24, 0, 0), (4, 9, 0, 0)], [(1, 108, 0, 0), (2, 43, 0, 0), (2, 15, 2, 16), (2, 11, 2, 12)], [(2, 68, 0, 0), (4, 27, 0, 0), (4, 19, 0, 0), (4, 15, 0, 0)], [(2, 78, 0, 0), (4, 31, 0, 0), (2, 14, 4, 15), (4, 13, 1, 14)], [(2, 97, 0, 0), (2, 38, 2, 39), (4, 18, 2, 19), (4, 14, 2, 15)], [(2, 116, 0, 0), (3, 36, 2, 37), (4, 16, 4, 17), (4, 12, 4, 13)], [(2, 68, 2, 69), (4, 43, 1, 44), (6, 19, 2, 20), (6, 15, 2, 16)], [(4, 81, 0, 0), (1, 50, 4, 51), (4, 22, 4, 23), (3, 12, 8, 13)], [(2, 92, 2, 93), (6, 36, 2, 37), (4, 20, 6, 21), (7, 14, 4, 15)], [(4, 107, 0, 0), (8, 37, 1, 38), (8, 20, 4, 21), (12, 11, 4, 12)], [(3, 115, 1, 116), (4, 40, 5, 41), (11, 16, 5, 17), (11, 12, 5, 13)], [(5, 87, 1, 88), (5, 41, 5, 42), (5, 24, 7, 25), (11, 12, 7, 13)], [(5, 98, 1, 99), (7, 45, 3, 46), (15, 19, 2, 20), (3, 15, 13, 16)], [(1, 107, 5, 108), (10, 46, 1, 47), (1, 22, 15, 23), (2, 14, 17, 15)], [(5, 120, 1, 121), (9, 43, 4, 44), (17, 22, 1, 23), (2, 14, 19, 15)], [(3, 113, 4, 114), (3, 44, 11, 45), (17, 21, 4, 22), (9, 13, 16, 14)], [(3, 107, 5, 108), (3, 41, 13, 42), (15, 24, 5, 25), (15, 15, 10, 16)], [(4, 116, 4, 117), (17, 42, 0, 0), (17, 22, 6, 23), (19, 16, 6, 17)], [(2, 111, 7, 112), (17, 46, 0, 0), (7, 24, 16, 25), (34, 13, 0, 0)], [(4, 121, 5, 122), (4, 47, 14, 48), (11, 24, 14, 25), (16, 15, 14, 16)], [(6, 117, 4, 118), (6, 45, 14, 46), (11, 24, 16, 25), (30, 16, 2, 17)], [(8, 106, 4, 107), (8, 47, 13, 48), (7, 24, 22, 25), (22, 15, 13, 16)], [(10, 114, 2, 115), (19, 46, 4, 47), (28, 22, 6, 23), (33, 16, 4, 17)], [(8, 122, 4, 123), (22, 45, 3, 46), (8, 23, 26, 24), (12, 15, 28, 16)], [(3, 117, 10, 118), (3, 45, 23, 46), (4, 24, 31, 25), (11, 15, 31, 16)], [(7, 116, 7, 117), (21, 45, 7, 46), (1, 23, 37, 24), (19, 15, 26, 16)], [(5, 115, 10, 116), (19, 47, 10, 48), (15, 24, 25, 25), (23, 15, 25, 16)], [(13, 115, 3, 116), (2, 46, 29, 47), (42, 24, 1, 25), (23, 15, 28, 16)], [(17, 115, 0, 0), (10, 46, 23, 47), (10, 24, 35, 25), (19, 15, 35, 16)], [(17, 115, 1, 116), (14, 46, 21, 47), (29, 24, 19, 25), (11, 15, 46, 16)], [(13, 115, 6, 116), (14, 46, 23, 47), (44, 24, 7, 25), (59, 16, 1, 17)], [(12, 121, 7, 122), (12, 47, 26, 48), (39, 24, 14, 25), (22, 15, 41, 16)], [(6, 121, 14, 122), (6, 47, 34, 48), (46, 24, 10, 25), (2, 15, 64, 16)], [(17, 122, 4, 123), (29, 46, 14, 47), (49, 24, 10, 25), (24, 15, 46, 16)], [(4, 122, 18, 123), (13, 46, 32, 47), (48, 24, 14, 25), (42, 15, 32, 16)], [(20, 117, 4, 118), (40, 47, 7, 48), (43, 24, 22, 25), (10, 15, 67, 16)], [(19, 118, 6, 119), (18, 47, 31, 48), (34, 24, 34, 25), (20, 15, 61, 16)]
        ]
    
    
    
    """
    ******  for matrix.py  *******
    """
    # Alignment Pattern Locations
    # 对齐模式位置
    alig_location = [
        (6, 18), (6, 22), (6, 26), (6, 30), (6, 34), (6, 22, 38), (6, 24, 42), (6, 26, 46), (6, 28, 50), (6, 30, 54), (6, 32, 58), (6, 34, 62), (6, 26, 46, 66), (6, 26, 48, 70), (6, 26, 50, 74), (6, 30, 54, 78), (6, 30, 56, 82), (6, 30, 58, 86), (6, 34, 62, 90), (6, 28, 50, 72, 94), (6, 26, 50, 74, 98), (6, 30, 54, 78, 102), (6, 28, 54, 80, 106), (6, 32, 58, 84, 110), (6, 30, 58, 86, 114), (6, 34, 62, 90, 118), (6, 26, 50, 74, 98, 122), (6, 30, 54, 78, 102, 126), (6, 26, 52, 78, 104, 130), (6, 30, 56, 82, 108, 134), (6, 34, 60, 86, 112, 138), (6, 30, 58, 86, 114, 142), (6, 34, 62, 90, 118, 146), (6, 30, 54, 78, 102, 126, 150), (6, 24, 50, 76, 102, 128, 154), (6, 28, 54, 80, 106, 132, 158), (6, 32, 58, 84, 110, 136, 162), (6, 26, 54, 82, 110, 138, 166), (6, 30, 58, 86, 114, 142, 170)
        ]
    
    # List of all Format Information Strings
    # [
    #   level1[mask_pattern0, mask_pattern1, mask_...3,...], 
    #   level2[...], 
    #   level3[...], 
    #   level4[...]
    #   ]    
    # 所有格式信息字符串的列表
    format_info_str = [
        ['111011111000100', '111001011110011', '111110110101010', '111100010011101', '110011000101111', '110001100011000', '110110001000001', '110100101110110'], ['101010000010010', '101000100100101', '101111001111100', '101101101001011', '100010111111001', '100000011001110', '100111110010111', '100101010100000'], ['011010101011111', '011000001101000', '011111100110001', '011101000000110', '010010010110100', '010000110000011', '010111011011010', '010101111101101'], ['001011010001001', '001001110111110', '001110011100111', '001100111010000', '000011101100010', '000001001010101', '000110100001100', '000100000111011']
        ]
    
    # Version Information Strings
    # 版本信息字符串
    version_info_str = [
        '000111110010010100', '001000010110111100', '001001101010011001', '001010010011010011', '001011101111110110', '001100011101100010', '001101100001000111', '001110011000001101', '001111100100101000', '010000101101111000', '010001010001011101', '010010101000010111', '010011010100110010', '010100100110100110', '010101011010000011', '010110100011001001', '010111011111101100', '011000111011000100', '011001000111100001', '011010111110101011', '011011000010001110', '011100110000011010', '011101001100111111', '011110110101110101', '011111001001010000', '100000100111010101', '100001011011110000', '100010100010111010', '100011011110011111', '100100101100001011', '100101010000101110', '100110101001100100', '100111010101000001', '101000110001101001'
        ]
    
    

    用到的一些常量

    data.py

    # -*- coding: utf-8 -*-
    
    from MyQR.mylibs.constant import char_cap, required_bytes, mindex, lindex, num_list, alphanum_list, grouping_list, mode_indicator
           
    # ecl: Error Correction Level(L,M,Q,H)
    def encode(ver, ecl, str):
        # 模式编码
        mode_encoding = {
                'numeric': numeric_encoding,
                'alphanumeric': alphanumeric_encoding,
                'byte': byte_encoding,
                'kanji': kanji_encoding
                }
        
        # 确定编码模式
        ver, mode = analyse(ver, ecl, str)
        
        print('line 16: mode:', mode)
        
        # mode_indicator[mode]:模式标识符 'numeric': '0001', 'alphanumeric': '0010', 'byte': '0100', 'kanji': '1000'
        # get_cci(ver, mode, str):计算字符数
        # mode_encoding[mode](str):编码字符串(word)
        code = mode_indicator[mode] + get_cci(ver, mode, str) + mode_encoding[mode](str)
        
        # Add a Terminator
        # 添加编码终止符
        rqbits = 8 * required_bytes[ver-1][lindex[ecl]]
        b = rqbits - len(code)
        code += '0000' if b >= 4 else '0' * b
        
        # 编成8bit码字
        # Make the Length a Multiple of 8
        # 长度不足补全
        while len(code) % 8 != 0:
            code += '0'
        
        # Add Pad Bytes if the String is Still too Short
        # 如果编码后的数据不足版本及纠错级别的最大容量,则在尾部补充 "11101100" 和 "00010001",直到全部填满。
        while len(code) < rqbits:    
            code += '1110110000010001' if rqbits - len(code) >= 16 else '11101100'
        
        # 分组编码
        data_code = [code[i:i+8] for i in range(len(code)) if i%8 == 0]
        data_code = [int(i,2) for i in data_code]
    
        g = grouping_list[ver-1][lindex[ecl]]
        data_codewords, i = [], 0
        for n in range(g[0]):
            data_codewords.append(data_code[i:i+g[1]])
            i += g[1]
        for n in range(g[2]):
            data_codewords.append(data_code[i:i+g[3]])
            i += g[3]
        
        return ver, data_codewords
    
    # 确定编码模式和版本
    def analyse(ver, ecl, str):
        if all(i in num_list for i in str):
            mode = 'numeric'
        elif all(i in alphanum_list for i in str):
            mode = 'alphanumeric'
        else:
            mode = 'byte'
        
        # 根据编码模式和纠错信息确定能容纳所有信息的最小版本
        # 如果比输入的参数小则不修改
        # 如果比输入的参数大则修改
        m = mindex[mode]
        l = len(str)
        for i in range(40):
            if char_cap[ecl][i][m] > l:
                ver = i + 1 if i+1 > ver else ver
                break
     
        return ver, mode
    
    # 数字编码
    def numeric_encoding(str):   
        str_list = [str[i:i+3] for i in range(0,len(str),3)]
        code = ''
        for i in str_list:
            rqbin_len = 10
            if len(i) == 1: 
                rqbin_len = 4
            elif len(i) == 2:
                rqbin_len = 7
            code_temp = bin(int(i))[2:]
            code += ('0'*(rqbin_len - len(code_temp)) + code_temp)
        return code
    
    # 字母数字编码
    def alphanumeric_encoding(str):
        code_list = [alphanum_list.index(i) for i in str]
        code = ''
        for i in range(1, len(code_list), 2):
            c = bin(code_list[i-1] * 45 + code_list[i])[2:]
            c = '0'*(11-len(c)) + c
            code += c
        if i != len(code_list) - 1:
            c = bin(code_list[-1])[2:]
            c = '0'*(6-len(c)) + c
            code += c
        
        return code
    
    # 字节编码
    def byte_encoding(str):
        code = ''
        for i in str:
            c = bin(ord(i.encode('iso-8859-1')))[2:]
            c = '0'*(8-len(c)) + c
            code += c
        return code
        
    # 中文字符编码不支持
    def kanji_encoding(str):
        pass
        
    # cci: character count indicator
    # 计算字符数
    def get_cci(ver, mode, str):
        if 1 <= ver <= 9:
            cci_len = (10, 9, 8, 8)[mindex[mode]]
        elif 10 <= ver <= 26:
            cci_len = (12, 11, 16, 10)[mindex[mode]]
        else:
            cci_len = (14, 13, 16, 12)[mindex[mode]]
            
        cci = bin(len(str))[2:]
        cci = '0' * (cci_len - len(cci)) + cci
        return cci
        
    if __name__ == '__main__':
        s = '123456789'
        v, datacode = encode(1, 'H', s)
        print(v, datacode)
    

    按照字符内容确定版本和模式,然后编码字符串。

    ECC.py

    # -*- coding: utf-8 -*-
    
    from MyQR.mylibs.constant import GP_list, ecc_num_per_block, lindex, po2, log
     
    #ecc: Error Correction Codewords
    # 得到纠错码字
    def encode(ver, ecl, data_codewords):
        en = ecc_num_per_block[ver-1][lindex[ecl]]  # 错误纠正码字
        ecc = []
        for dc in data_codewords:
            ecc.append(get_ecc(dc, en))
        return ecc
    
    def get_ecc(dc, ecc_num):
        gp = GP_list[ecc_num]   # 得到适当的项乘生成多项式
        remainder = dc
        for i in range(len(dc)):
            remainder = divide(remainder, *gp)  # 使用消息多项式(在第一个乘法步骤中)或余数(在所有后续乘法步骤中)对结果进行异或
        return remainder
    
    # 得到余数
    def divide(MP, *GP):
        if MP[0]:
            GP = list(GP)
            for i in range(len(GP)):
                GP[i] += log[MP[0]]
                if GP[i] > 255:
                    GP[i] %= 255
                GP[i] = po2[GP[i]]
            return XOR(GP, *MP)
        else:
            return XOR([0]*len(GP), *MP)
        
    # 异或
    def XOR(GP, *MP):
        MP = list(MP)
        a = len(MP) - len(GP)
        if a < 0:
            MP += [0] * (-a)
        elif a > 0:
            GP += [0] * a
        
        remainder = []
        for i in range(1, len(MP)):
            remainder.append(MP[i]^GP[i])
        return remainder
    

    得到纠错码字步骤:

    1. 找到适当的项乘生成多项式,使得乘法的结果与消息多项式具有相同的第一项。
    2. 使用消息多项式(在第一个乘法步骤中)或余数(在所有后续乘法步骤中)对结果进行异或。
    3. 执行这些步骤n次,其中n是消息多项式中的系数。

    structure.py

    # -*- coding: utf-8 -*-
    
    from MyQR.mylibs.constant import required_remainder_bits, lindex, grouping_list
    
    def structure_final_bits(ver, ecl, data_codewords, ecc):
        # 将产生的序列按次序放到分块中
        final_message = interleave_dc(ver, ecl, data_codewords) + interleave_ecc(ecc)
        
        # convert to binary & Add Remainder Bits if Necessary
        # 转换为二进制 如果必要则添加余数位
        final_bits = ''.join(['0'*(8-len(i))+i for i in [bin(i)[2:] for i in final_message]]) + '0' * required_remainder_bits[ver-1]
        
        return final_bits
    
    # 数据区块
    def interleave_dc(ver, ecl, data_codewords):
        id = []
        for t in zip(*data_codewords):
            id += list(t)
        g = grouping_list[ver-1][lindex[ecl]]
        if g[3]:
            for i in range(g[2]):
                id.append(data_codewords[i-g[2]][-1])
        return id
        
    # 纠错码字区块
    def interleave_ecc(ecc):
        ie = []
        for t in zip(*ecc):
            ie += list(t)
        return ie
    

    按规定把数据分块,然后对每一块进行计算,得出相应的纠错码字区块,把纠错码字区块 按顺序构成一个序列,添加到原先的数据码字序列后面。

    matrix.py

    # -*- coding: utf-8 -*-
         
    from MyQR.mylibs.constant import alig_location, format_info_str, version_info_str, lindex
        
    def get_qrmatrix(ver, ecl, bits):
        num = (ver - 1) * 4 + 21
        qrmatrix = [[None] * num for i in range(num)]   # 构造矩阵
        #  [([None] * num * num)[i:i+num] for i in range(num * num) if i % num == 0] 
    
        # Add the Finder Patterns & Add the Separators
        # 添加查找器模式和添加分隔符
        add_finder_and_separator(qrmatrix)
        
        # Add the Alignment Patterns
        # 添加校准模式
        add_alignment(ver, qrmatrix)
        
        # Add the Timing Patterns
        # 添加时间模式
        add_timing(qrmatrix)
        
        # Add the Dark Module and Reserved Areas
        # 添加涂黑模块和保留区域
        add_dark_and_reserving(ver, qrmatrix)
        
        maskmatrix = [i[:] for i in qrmatrix]
        
        # Place the Data Bits
        # 放置数据位
        place_bits(bits, qrmatrix)
        
        # Data Masking
        # 掩摸图形
        mask_num, qrmatrix = mask(maskmatrix, qrmatrix)
        
        # Format Information
        # 格式信息
        add_format_and_version_string(ver, ecl, mask_num, qrmatrix)
    
        return qrmatrix
    
    # 添加查找器模式和添加分隔符(左上角 右上角 左下角矩形和空白部分)
    def add_finder_and_separator(m):             
        for i in range(8):
            for j in range(8):
                if i in (0, 6):
                    m[i][j] = m[-i-1][j] = m[i][-j-1] = 0 if j == 7 else 1
                elif i in (1, 5):
                    m[i][j] = m[-i-1][j] = m[i][-j-1] = 1 if j in (0, 6) else 0  
                elif i == 7:
                    m[i][j] = m[-i-1][j] = m[i][-j-1] = 0
                else:
                    m[i][j] = m[-i-1][j] = m[i][-j-1] = 0 if j in (1, 5, 7) else 1
    
    # 添加校准模式(矩形校正图形)
    def add_alignment(ver, m):
        if ver > 1:
            coordinates = alig_location[ver-2]
            for i in coordinates:
                for j in coordinates:
                    if m[i][j] is None:
                        add_an_alignment(i, j, m)
    
    # 添加一个校正图形
    def add_an_alignment(row, column, m):
        for i in range(row-2, row+3):
            for j in range(column-2, column+3):
                m[i][j] = 1 if i in (row-2, row+2) or j in (column-2, column+2) else 0
        m[row][column] = 1
    
    # 添加时间模式
    def add_timing(m):
        for i in range(8, len(m)-8):
            m[i][6] = m[6][i] = 1 if i % 2 ==0 else 0
        
    # 添加涂黑模块和保留区域
    def add_dark_and_reserving(ver, m):
        for j in range(8):
            m[8][j] = m[8][-j-1] = m[j][8] = m[-j-1][8] = 0
        m[8][8] = 0
        m[8][6] = m[6][8] = m[-8][8] = 1
        
        if ver > 6:
            for i in range(6):
                for j in (-9, -10, -11):
                    m[i][j] = m[j][i] = 0
                
    # 放置数据位            
    def place_bits(bits, m):
        bit = (int(i) for i in bits)
    
        up = True
        for a in range(len(m)-1, 0, -2):
            a = a-1 if a <= 6 else a
            irange = range(len(m)-1, -1, -1) if up else range(len(m))
            for i in irange:
                for j in (a, a-1):
                    if m[i][j] is None:
                        m[i][j] = next(bit)
            up = not up
    
    # 将掩摸图形用于符号的编码区域,使得二维码图形中的深色和浅色(黑色和白色)区域能够比率最优的分布。
    def mask(mm, m):
        mps = get_mask_patterns(mm)
        scores = []
        for mp in mps:
            for i in range(len(mp)):
                for j in range(len(mp)):
                    mp[i][j] = mp[i][j] ^ m[i][j]
            scores.append(compute_score(mp))
        best = scores.index(min(scores))
        return best, mps[best]
        
    def get_mask_patterns(mm):
        def formula(i, row, column):
            if i == 0:
                return (row + column) % 2 == 0
            elif i == 1:
                return row % 2 == 0
            elif i == 2:
                return column % 3 == 0
            elif i == 3:
                return (row + column) % 3 == 0
            elif i == 4:
                return (row // 2 + column // 3) % 2 == 0
            elif i == 5:
                return ((row * column) % 2) + ((row * column) % 3) == 0
            elif i == 6:
                return (((row * column) % 2) + ((row * column) % 3)) % 2 == 0
            elif i == 7:
                return 	(((row + column) % 2) + ((row * column) % 3)) % 2 == 0
    
        mm[-8][8] = None
        for i in range(len(mm)):
            for j in range(len(mm)):
                mm[i][j] = 0 if mm[i][j] is not None else mm[i][j]
        mps = []
        for i in range(8):
            mp = [ii[:] for ii in mm]
            for row in range(len(mp)):
                for column in range(len(mp)):
                    mp[row][column] = 1 if mp[row][column] is None and formula(i, row, column) else 0
            mps.append(mp)
            
        return mps
                
    def compute_score(m):
        def evaluation1(m):
            def ev1(ma):
                sc = 0
                for mi in ma:
                    j = 0
                    while j < len(mi)-4:
                        n = 4
                        while mi[j:j+n+1] in [[1]*(n+1), [0]*(n+1)]:
                            n += 1
                        (sc, j) = (sc+n-2, j+n) if n > 4 else (sc, j+1)
                return sc
            return ev1(m) + ev1(list(map(list, zip(*m))))
            
        def evaluation2(m):
            sc = 0
            for i in range(len(m)-1):
                for j in range(len(m)-1):
                    sc += 3 if m[i][j] == m[i+1][j] == m[i][j+1] == m[i+1][j+1] else 0
            return sc
            
        def evaluation3(m):
            def ev3(ma):
                sc = 0
                for mi in ma:
                    j = 0
                    while j < len(mi)-10:
                        if mi[j:j+11] == [1,0,1,1,1,0,1,0,0,0,0]:
                            sc += 40
                            j += 7
                        elif mi[j:j+11] == [0,0,0,0,1,0,1,1,1,0,1]:
                            sc += 40
                            j += 4
                        else:
                            j += 1
                return sc
            return ev3(m) + ev3(list(map(list, zip(*m))))
            
        def evaluation4(m):
            darknum = 0
            for i in m:
                darknum += sum(i)
            percent = darknum  / (len(m)**2) * 100
            s = int((50 - percent) / 5) * 5
            return 2*s if s >=0 else -2*s
    
        score = evaluation1(m) + evaluation2(m)+ evaluation3(m) + evaluation4(m)
        return score
        
    # 生成格式和版本信息放入相应区域内
    def add_format_and_version_string(ver, ecl, mask_num, m):
        fs = [int(i) for i in format_info_str[lindex[ecl]][mask_num]]
        for j in range(6):
            m[8][j] = m[-j-1][8] = fs[j]
            m[8][-j-1] = m[j][8] = fs[-j-1]
        m[8][7] = m[-7][8] = fs[6]
        m[8][8] = m[8][-8] = fs[7]
        m[7][8] = m[8][-7] = fs[8]
        
        # 版本7-40都包含了版本信息,没有版本信息的全为0。
        if ver > 6:
            vs = (int(i) for i in version_info_str[ver-7])
            for j in range(5, -1, -1):
                for i in (-9, -10, -11):
                    m[i][j] = m[j][i] = next(vs)
    

    构造矩阵:将探测图形、分隔符、定位图形、校正图形、格式和版本信息和码字模块放入矩阵中。
    掩摸:将掩摸图形用于符号的编码区域,使得二维码图形中的深色和浅色(黑色和白色)区域能够比率最优的分布。

    draw.py

    # -*- coding: utf-8 -*-
    
    from PIL import Image
    import os
    
    def draw_qrcode(abspath, qrmatrix):
        unit_len = 3
        x = y = 4*unit_len
        pic = Image.new('1', [(len(qrmatrix)+8)*unit_len]*2, 'white')   # 新建一张白色的底图
        
        # 循环矩阵中的单位,在需要涂黑的单位启用dra_a_black_unit()函数涂黑。
        for line in qrmatrix:
            for module in line:
                if module:
                    draw_a_black_unit(pic, x, y, unit_len)
                x += unit_len
            x, y = 4*unit_len, y+unit_len
    
        saving = os.path.join(abspath, 'qrcode.png')
        pic.save(saving)    # 保存二维码图片
        return saving
        
    # 画出黑单位
    def draw_a_black_unit(p, x, y, ul):
        for i in range(ul):
            for j in range(ul):
                p.putpixel((x+i, y+j), 0)
    

    根据构造出来的矩形画出二维码

    参考文章

    QR二维码编码原理
    MyQR源码解读
    二维码 编码原理简介

    展开全文
  • 使用MyQR和qrcode来制作二维码。一维条形码,就是我们日常所说的条形码(Barcod),常见于食品包装上。它是将宽度不等的多个黑条和空白,按一定的编码规则排列,用以表达一组信息的图形标识符。常见的一维条形码是由...

    一、前言

    • 一维条形码,就是我们日常所说的条形码(Barcod),常见于食品包装上。它是将宽度不等的多个黑条和空白,按一定的编码规则排列,用以表达一组信息的图形标识符。常见的一维条形码是由黑条(简称条)和白条(简称空)排成平行线图案。条形码可以标出物品的生产国、制造厂家、商品名称、生产日期以及图书分类号、邮件起止地点、类别、日期等信息。通常一维条形码所能表示的字符集不过 10 个数字、26个英文字母及一些特殊字符,条码字符集最大所能表示的字符个数为 128 个 ASCII 字符,信息量非常有限。
    • 二维码( 2 − Dimensional Barcode),又称二维条形码。它是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形来记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理。
    • 二维码有其特定的字符集,每个字符占有一定的宽度,每种码具有一定的校验功能,同时还具有对不同行的信息自动识别功能、及处理图形旋转变化等特点。二维条形码是在二维空间水平和竖直方向存储信息的条形码。它的优点是信息容量大,译码可靠性高,纠错能力强,制作成本低,保密与防伪性能好。

    常见的二维码为 QR Code,QR全称是Quick Response&#x

    展开全文
  • python利用myqr库生成二维码

    千次阅读 2020-01-17 14:36:59
    1、今天,来学习一下利用myqr库来生成二维码,首先,先执行命令安装myqr这个库,输入以下命令: pip install myqr 2、安装成功后,在本地的磁盘底下建一个目录,这里我存放的目录为:E:\study\myqr 3、进入...

    1、今天,来学习一下利用myqr库来生成二维码,首先,先执行命令安装myqr这个库,输入以下命令:

    pip install myqr

    2、安装成功后,在本地的磁盘底下建一个目录,这里我存放的目录为:E:\study\myqr

    3、进入这个目录底下,输入python回车之后,

    (1)、生成普通二维码,输入以下的代码:

    from MyQR import myqr
    myqr.run(words='http://www.baidu.com')

    如下图所示,此时会在这个目录底下生成一张qrcode.png的二维码图片:

    (2)、生成带图片的二维码,输入以下的代码:

    myqr.run(words='http://www.baidu.com', picture='test.png',colorized=True)

    注:此为彩色图片代码,需要黑白图片就去掉参数colorized=True,上面的图片和代码是存放同一个路径的,如果找不到图片路径的话,可以修改一下picture参数。

    如下图所示,此时会在这个目录底下生成一个test_prcode.png的二维码图片:

    (3)、生成动态二维码,输入以下的代码:

    myqr.run(words='http://www.baidu.com', picture='test.gif',colorized=True)

    如下图所示,此时会在这个目录底下生成一个test_prcode.gif的二维码图片:

    4、完整的相关参数可以参考这个py文件,代码如下:

    # 先导入myqr模块
    from MyQR import myqr
    
    
    myqr.run(
        words='http://www.baidu.com',
        # 扫描二维码后,显示的内容,或是跳转的链接
        version=5,  # 设置容错率
        level='H',  # 控制纠错水平,范围是L、M、Q、H,从左到右依次升高
        picture='test.gif',  # 图片所在目录,可以是动图
        colorized=False,  # 黑白(False)还是彩色(True)
        contrast=1.0,  # 用以调节图片的对比度,1.0 表示原始图片。默认为1.0。
        brightness=1.0,  # 用来调节图片的亮度,用法同上。
        save_name='test_qrcode2.gif',  # 控制输出文件名,格式可以是 .jpg, .png ,.bmp ,.gif
    )
    	
    	
    # 如果不设置这个save_name参数,并且也不想生成图片、动态二维码时,默认生成的图片名称为qrcode.png
    # 如果不设置这个save_name参数,并且加了picture参数,如test.gif,生成的即为test_qrcode.gif,如test.jpg,生成的即为test_qrcode.jpg
    # 报错:Wrong picture! Input a filename that exists and be tailed with one of {'.jpg', '.png', '.bmp', '.gif'}!
    # 解决方案:picture与save_name 设置一致

    5、输入命令,python test.py之后,如下图所示,便生成一个黑白的test_qrcode2.gif的动态二维码了:

    6、以上内容仅供学习参考,谢谢!

    展开全文
  • Python中使用myqr生成gif动态二维码源码以及资源,
  • 有趣的二维码:使用MyQR和qrcode来制作二维码

    千次阅读 热门讨论 2020-10-01 00:08:23
    本篇博客主要介绍了两个制作二维码的第三方库,分别是MyQR和qrcode,并用Python制作了几个不同样式的二维码。
  • 使用Python制作酷炫二维码(myqr)

    万次阅读 2019-08-26 22:31:11
    安装myqr和安装普通的python一样,很简单,使用 pip 安装即可 pip install myqr 看到这样提示: 2、使用方式 该库在命令行中运行,你只需要传递网址链接、图片地址等参数,就可以生成相应的二维码...
  • 安装myqr MyQR跟其他的python库一样,可以通过pip来进行安装和管理: [dechin@dechin-manjaro myqr]$ python3 -m pip install myqr Collecting myqr Downloading MyQR-2.3.1.zip (16 kB) Requirement already ...
  • from MyQR import myqr import os myqr.run( words='Hello world', #在命令后输入链接或者句子作为参数,然后在程序的当前目录中产生相应的二维码图片文件,默认命名为” qrcode.png“ version=1, #设置容错率为最高...
  • MyQR源码学习

    千次阅读 2019-02-09 10:59:29
    源码连接:... 1.MyQR文件结构 qrcode │ LICENSE.md │ README.md │ requirements.txt #环境依赖文件 | myqr.py | └───MyQR │ │ __init__.py │ │ myqr.py #调用的文件 │ ...
  • 1.安装MyQR, pip installMyQR。 from MyQR import myqr """生成一个二维码""" myqr.run( words='Hello,China', // 内容/链接 save_name='D:\\workspace\\pytest\\pic\\001.jpg', // 生产二维码存储位置 ) ...
  • python中的myqr模块生成多种二维码

    千次阅读 2019-09-14 19:13:19
    python利用myqr 模块生成多种二维码 首先 使用 pip install myqr pip install myqr myqr 模块主要参数说明 -v :定义二维码的大小,范围为 1 ~ 40,默认大小取决于输入的内容 -l : 定义二维码纠错率,也就是...
  • python模块之MyQR——制作个性化二维码

    万次阅读 多人点赞 2019-11-28 12:34:31
    安装MyQR 模块使用 模块参数介绍 简单的二维码 带图片的二维码 带动态图片的二维码 其他参数 概述 MyQR模块可以生成个性化的二维码图片。 安装MyQR 如果没有安装,那么就需要安装:pip install MyQR。 ...
  • MyQR二维码生成

    2014-06-08 23:19:03
    二维码生成(支持logo) 支持自动调整 QRCode version 支持指定 QRCode version 支持自动容错等级 支持指定容错等级 支持中心logo 支持自动调整logo大小 支持URL获取Logo
  • <p><img alt="" height="167" src="https://img-ask.csdnimg.cn/upload/1604738761936.png" width="606" />什么办法都尝试了,就是不知道问题在哪里,安装下载也是通过pip的,怎么就有这个问题了,急求大神帮忙!...
  • Python MyQR 生成不一样的二维码MyQR 最近,闲暇时学习了一点Python的东西,还是比较有趣,想和大家分享一下。顺便说一句,Python 真的很好玩 [手动滑稽] MyQR 二维码又称二维条码,常见的二维码为QR Code,QR...
  • Python入门(十八):MyQR 二维码制作

    万次阅读 多人点赞 2019-03-26 15:49:29
    Python的二维码制作:利用MyQR库生成生动有趣的二维码
  • 1.myqr库、qrcode库的下载 利用pip命令直接下载: pip install myqr pip install qrcode pypi换源:由于pypi源默认为国外源,有下载速度慢和经常被墙导致不可用的缺点,所以安装软件时pip源最好更换为国内资源 ...
  • Python包--MyQR模块使用体会MyQR代码参数列表运行结果注意事项 MyQR Github中文官网链接 作用:生成个性化二维码。 代码 运行环境PyCharm #!/usr/bin/python # -*- coding: UTF-8 -*- """ @author:Neal_caffrey @...
  • ​二维码相信大家并不陌生 随着智能设备的发展 做什么事情都离不开扫码 买单需要支付码 出门需要健康码 地铁需要乘车码 …… 以后墓碑上也不用写碑文了 刻个二维码上去 手机一扫就了解逝者生平了 ...MyQR是一个pyth...
  • 利用myqr库创建自己的二维码

    千次阅读 2020-11-21 23:01:24
    利用myqr库创建自己的二维码 相信朋友们都看过各种群里钓鱼的涩图二维码吧(手动滑稽),今天学了一下制作方式(myqr库的使用),在这里分享一下这个整活利器。 首先配置好python3的环境(也可以用anaconda)和...
  • python的实现代码 确保当前目录为Code,在...from MyQR import myqr >>>myqr.run('https://www.shiyanlou.com') 参考地址:https://www.lanqiao.cn/courses/1126/learning/?id=7103 参数 含义 详细 w

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,499
精华内容 599
关键字:

myqr