手头有一个这样的需求,制作自定义二维码,要求在二维码中插入图片,作为 A Coder,最直接了当的方式当然是通过书写优美的代码来实现,而人生苦短,我用 Python,陆陆续续捣鼓了几个小时,算是初步完成了,分享下经验。
查阅资料得知,Python 制作二维码的库常见的有 qrcode 和 myqr 两个,下面我分别给出一个 qrcode 和 myqr 制作自定义二维码的一个实例。
但是在动手编码之前,最好还是弄清楚二维码的原理。
二维码的原理
二维码的定义
二维条码 (2-dimensional bar code),也称二维码是用某种特定的几何图形按一定规律在平面(二维方向上) 分布的黑白相间的图形记录数据符号信息的。
在目前几十种二维条码中,常用的码制有:Data Matrix, Maxi Code, Aztec, QR Code, Vericode, PDF417, Ultracode, Code 49, Code 16K等。
1.堆叠式/行排式二维条码,如,Code 16K、Code 49、PDF41,感兴趣的同学可以查阅资料深入了解下。
2.矩阵式二维码,最流行莫过于 QR CODE。很多时候,人们经常把 QR CODE 和二维码画上等号,殊不知, QR CODE 只是二维码的一种而已。
二维码是相对于一维码来说的,它们均属于条码,以前在书本或者商品上常印有一维条形码,但现在二维码居多。
QR CODE 的特点
1、快速读取,QR 即 Quick Response 的缩写,见名知意。
2、高容量、高密度;理论上内容经过压缩处理后可以存7089个数字,4296 个字母和数字混合字符,2953个8位字节数据,1817个汉字。
3、支持纠错处理;QR码的纠错能力分为4个级别,分别是:
| 级别 | 纠错能力 |
|---|---|
| level L | 最多能够纠正 7% 的错误 |
| level M | 最多能够纠正 15% 的错误 |
| level Q | 最多能够纠正 25% 的错误 |
| level H | 最多能够纠正 30% 的错误 |
4、QR CODE 的大小 (Size) 被定义为版本(Version)。QR CODE 设有从 1到40 的不同版本(种类),每个版本都具备固有的码元结构(码元数)。(码元是指构成QR码的方形黑白点。) “码元结构”是指二维码中的码元数。从版本1(21码元×21码元)开始,在纵向和横向各自以4码元为单位递增,一直到版本40(177码元×177码元)。
Tips: 最后了解这些原理后再去看代码,不然可能一头雾水,所谓磨刀不误砍柴工~。
qrcode 库
构造函数 qrcode.QRCode()
qrcode.QRCode(version=20,error_correction=ERROR_CORRECT_H,box_size=10, border=1)
| 参数名 | 参数含义 |
|---|---|
| version | 控制二维码的大小,取值范围从1到40。取最小值1时,二维码大小为21*21。取值为 None (默认)或者使用fit=true参数(默认)时,二维码会自动调整大小。 |
| error_correction | 控制二维码纠错级别,四个参数 ERRORCORRECTL/M/Q/H 分别对应上一个表格中四种纠错能力 |
| box_size | 控制二维码中每个格子的像素数,默认为 10 |
| border | 控制二维码四周留白包含的格子数,默认为4 |
实例代码
# -*- coding: utf-8 -*-
# author: inspurer(月小水长)
# pc_type lenovo
# create_time: 2019/6/11 18:24
# file_name: my_qrcode.py
# github https://github.com/inspurer
# qq邮箱 2391527690@qq.com
# 微信公众号 月小水长(ID: inspurer)
import qrcode
from qrcode.constants import ERROR_CORRECT_H
from PIL import Image
def generateQRCode(data, imagePath):
qr = qrcode.QRCode(version=20,
error_correction=ERROR_CORRECT_H,
box_size=10, border=1)
# 添加自定义文本信息
qr.add_data(data)
# 二维码自动调整大小
qr.make(fit=True)
# 创建二维码图片
img = qr.make_image()
# print(img.getpixel((0,0)))
img = img.convert("RGBA")
# print(img.getpixel((0,0)))
icon = Image.open(imagePath)
img_w, img_h = img.size
factor = 4
# // 是整除
size_w = int(img_w / factor)
size_h = int(img_h / factor)
# 划重点,上面两句可以用这句话代替, 更 Pythonic,但是可读性没那么好
# size_w, size_h = map(lambda x: x//factor, img.size)
icon_w, icon_h = icon.size
if icon_w > size_w:
icon_w = size_w
if icon_h > size_h:
icon_h = size_h
# 做笔记,上面四句可以用下面两句代替,更 Pythonic
# icon_w = icon_w if icon_w<size_w else size_w
# icon_h = icon_h if icon_h<size_h else size_h
# 重新调整 icon 大小使之完美嵌入二维码中
icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS)
w = int((img_w - icon_w) / 2)
h = int((img_h - icon_h) / 2)
# print(icon.getpixel((0,0)),icon.mode)
icon = icon.convert("RGBA")
# print(icon.getpixel((0,0)))
# 把 icon 加到 img 上去
img.paste(icon, (w, h))
# 保存二维码
img.save('my_logo.png')
# 需要在当前路径下放置 raw.jpg
generateQRCode(data='https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzUzMDE5MzQ3Ng==#wechat_redirect', imagePath='raw.jpg')
注释写的比较详细,请慢慢品尝,如有疑问,欢迎留言。
如无意外(记得在工作路径下预留一个图片用作生成二维码用),运行上述代码后会在工作路径下保存生成的二维码,如下:
扫一扫即可看到编码在二维码中的信息,可以是 URL [ 如 add_data("inspurer.github.io")],也可以是一般文本 [ 如 add_data("月小水长")]
myqr 库
这个库相对而言,没有 qrcode 那么复杂,直接上代码
# -*- coding: utf-8 -*-
# author: inspurer(月小水长)
# pc_type lenovo
# create_time: 2019/6/11 18:24
# file_name: my_qrcode.py
# github https://github.com/inspurer
# qq邮箱 2391527690@qq.com
# 微信公众号 月小水长(ID: inspurer)
from MyQR import myqr
def myQRTest(data,imgPath):
version, level, qr_name = myqr.run(
words=data, # 不支持中文,支持 0~9,a~z, A~Z 以及常见的常用英文标点符号和空格
version=2, # 版本,从 1至 40
level='H', # 纠错等级,范围是L、M、Q、H,从左到右依次升高
picture=imgPath, # 需要嵌入二维码的图片
colorized=True, # True 为彩色,False 为黑白
contrast=1.0, # 对比度
brightness=1.0, # 亮度
save_name='my_qrcode2.png', # 格式可以是 jpg,png,bmp,gif
)
myQRTest('https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzUzMDE5MzQ3Ng==#wechat_redirect', 'raw.jpg')