如何用 Python 生成像微信名片那样的中间带有 Logo 的二维码?使用 Python 的qrcode模块可以很容易做到。

首先,import 所需的模块。完成工作,需要 qrcodePIL模块。安装这些模块的方法可以自行百度。

1
2
import qrcode
from PIL import Image, ImageFont, ImageDraw

接着,生成二维码。二维码仅至少接收一个文本参数。

1
2
3
4
5
6
7
def make_qrcode(text):
    qr = qrcode.QRCode(version=10, 
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=8,border=4)
    qr.add_data(text)
    qr.make(fit=True)
    return qr.make_image(fill_color="black", back_color="white")

参数说明:

  • version,通俗来说,用于控制二维码的尺寸。version=1时,二维码包含21个块,其后 version 每增加1,二维码块数增加4。因此,version=10包含21+4*9=57个块。每个块的实际像素,由下面的参数 box_size 决定。
  • error_correction,即容错率,按照「草料二维码」的建议,应当选择30%,这个比例下最容易被各种设备识别,也就是常量qrcode.constants.ERROR_CORRECT_H。其他的常量还有:
    • ERROR_CORRECT_L,大约7%容错;
    • ERROR_CORRECT_M,大约15%容错,默认值;
    • ERROR_CORRECT_Q,大约25%容错率。
  • box_size,即每个块的占据的像素数,8就是8像素。
  • border,即二维码区域在边缘的留白,数字是块数,比如border=4即4块,也就是是4*8=32像素的留白,默认是4,建议最小值也是4,不过可以根据实际情况调整。
  • 整体上,生成二维码实际大小这么算。(version 块数 + border 块数)* box_size,因此以上参数实际会生成(57 + 4)* 8 = 488像素大小的正方形。
  • 最后 make_image 方法中的参数,可以根据实际需要调整,默认值就是白底黑色二维码。

二维码生成了,下一步就是往二维码上添加 Logo。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 将logo添加到二维码中间,logo的尺寸为二维码的1/4,且居中显示;
# 同时为了美观,logo与二维码中间会有适当留白。
def add_image_to_center(back_image, logo_image):
    qrcode_size = back_image.size[0]
    # 创建一个qrcode大小的背景,用于解决黑色二维码粘贴彩色logo显示为黑白的问题。
    qr_back = Image.new('RGBA', back_image.size, 'white')
    qr_back.paste(back_image)
    logo_background_size = int(qrcode_size / 4)
    # 创建一个尺寸为二维码1/4的白底logo背景
    logo_background_image = Image.new('RGBA', (logo_background_size, logo_background_size), 'white')
    # logo与其白底背景设置背景尺寸1/20的留白
    logo_offset = int(logo_background_size / 20)
    logo_size = int(logo_background_size - logo_offset * 2)
	# 将 logo 缩放至适当尺寸
    resized_logo = logo_image.resize((logo_size, logo_size))
    # 将logo添加到白色背景
    logo_background_image.paste(resized_logo, box=(logo_offset, logo_offset))
    # 将白色背景添加到二维码图片
    logo_background_offset = int((qrcode_size - logo_background_size) / 2)
    qr_back.paste(logo_background_image, box=(logo_background_offset, logo_background_offset))
    return qr_back

以上代码中,需要说明的是关于第5行的问题。我发现直接往白底黑色二维码上粘贴彩色 Logo 会造成 Logo 显示为黑白色颗粒的问题。网上一时找不到解决方案,就只好折衷一下,先创建一个与二维码底色一样的背景 image,然后把二维码以及 logo 都粘贴到这个背景上。只是一个曲线救国方案,如果谁有更好的方法,欢迎联系我。

最终,到了实际生成步骤了。

1
2
3
4
5
6
text_for_qrcode = r'www.baidu.com'
logo_image_file = r'avatar.jpg'
with Image.open(logo_image_file) as logo_image:
    qr_code = make_qrcode(text_for_qrcode)
    qr_code_with_logo = add_image_to_center(qr_code, logo_image)
    qr_code_with_logo.save('qr.png')

最终效果如下图所示:

qr