手头有一个这样的需求,制作自定义二维码,要求在二维码中插入图片,作为 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等。
二维码是相对于一维码来说的,它们均属于条码,以前在书本或者商品上常印有一维条形码,但现在二维码居多。
级别 | 纠错能力 |
---|---|
level L | 最多能够纠正 7% 的错误 |
level M | 最多能够纠正 15% 的错误 |
level Q | 最多能够纠正 25% 的错误 |
level H | 最多能够纠正 30% 的错误 |
QR CODE 的大小 (Size) 被定义为版本(Version)。QR CODE 设有从 1 到 40 的不同版本(种类),每个版本都具备固有的码元结构(码元数)。(码元是指构成 QR 码的方形黑白点。) “码元结构”是指二维码中的码元数。从版本 1(21码元×21码元)开始,在纵向和横向各自以4码元为单位递增,一直到版本40(177码元×177码元)。
Tips: 最后了解这些原理后再去看代码,不然可能一头雾水,所谓磨刀不误砍柴工~。
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("https://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')
本期分享结束,下期再会~