0. 起因
众所周知,借刀杀人最为致命,聊天也是如此。
最近我的群聊画风逐渐变味:
当然,这种图片的生产成本很低,只需在设置页关闭昵称显示,把聊天背景重置为灰色,然后利用截图工具截图,最后保存到手机里,添加到表情包库中即可。
然而微信头像是会更改的,人的精力也是有限的,经过了两天的狂欢后,我们逐渐意识到这种文化的短期性。
但是,无所谓,我会出手!我灵光一闪,只要把数据来源从截图变成生成,那么即使微信头像更改,也可以随时替换,如此,便有了此文。
1. 准备工作
技术栈:Python内置的 PIL
(Pillow)库
头像文件:可以直接从微信中保存,我们给它命名为 logo.jpg
主脚本文件:main.py
(为了方便脚本编写,main.py
和 logo.jpg
放置在同一目录下)
提示:下面两张表是写完后折回来后补的
输入参数 | 含义 | 默认 |
---|---|---|
text | 要生成的话 | “Hello World” |
logo_path | 要生成的气泡用的头像 | “logo.jpg” |
save_path | 图片的保存路径及文件名 | “save.jpg” |
font_path | 字体的路径 | “fonts/msyhl.ttc” |
font_size | 字体的大小 | 25 |
space_lengh | 间隙的长度 | 20 |
bg_height | 背景的高度 | 64 |
输出 | 含义 |
---|---|
savepath | 一张图片文件 |
2. 脚本设计与编写
我们可以从微信上面随便截一下,看看大概的长度。
通过状态栏的提示可知:370x50
为这张图片的大小。
我们取一个看起来舒服一点的值,就 64
吧,作为我们绘图的高度,同时我们选择微软雅黑
作为。
至于宽度,我们现在已知左边的头像是一个正方形,正方形和右边的白色背景起泡之间的距离为 20
,起泡的长度又视文字的长度而定,所以背景的宽度也是不定的。
所以我们下一步是,如何估算出 文字生成后的大概大小?
2.1 估算文字生成后的大概大小
通过阅读博文:使用Python PIL库获取某个字体渲染后的文本的宽高(应用于检测翻译后的文本是否长度过长)
我们找到了方案,就是如下的一段函数:
fontsize=26
white = (255,255,255)
def get_font_render_size(text):
canvas = Image.new('RGB', (2048,2048))
draw = ImageDraw.Draw(canvas)
monospace = ImageFont.truetype("msyh.ttc", fontsize)
draw.text((0, 0), text, font=monospace, fill=white)
bbox = canvas.getbbox()
# 宽高
size = (bbox[2] - bbox[0], bbox[3] - bbox[1])
return size
# ————————————————
# 版权声明:本文为CSDN博主「林新发」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
# 原文链接:https://blog.csdn.net/linxinfa/article/details/116527440
具体原理可以去对应博文查看,这里就直接投入使用啦。
我们进行轻微改动后就可以得到函数,返回值为一个元组(宽, 高)
def get_font_render_size(text, font_path, font_size):
"""
:param text: 文字
:param font_path: 字体路径
:param font_size: 字体大小
:return: tuple 宽高
"""
canvas = Image.new('RGB', (2048, 2048))
ImageDraw.Draw(canvas).text((0, 0), text, font=ImageFont.truetype(font_path, font_size))
bbox = canvas.getbbox()
return bbox[2] - bbox[0], bbox[3] - bbox[1]
# 计算文字渲染后的长度
text_width, text_height = get_font_render_size(text, font_path, font_size)
之后我们用text_width
表示文字渲染后的长度
2.2 绘制背景
# 定义背景宽度
bg_width = text_width + space_length
bg_height
作为输入参数出现,无需定义。
# 生成背景
bg_img = Image.new(mode='RGB', size=(bg_width + 100, bg_height), color="#F5F5F5")
2.3 绘制头像
#读取头像文件,并绘制头像到背景图片
logo = Image.open(logo_path, mode="r")
logo = logo.resize((bg_height, bg_height))
bg_img.paste(logo, (0, 0))
2.4 绘制气泡
2.4.1 绘制圆角矩形
x, y, w, h, r = bg_height + space_length, 0, text_width + space_length * 1.5, bg_height, space_length
fill_color = "#FFFFFF"
draw_object = ImageDraw.Draw(bg_img)
draw_object.ellipse((x, y, x + r, y + r), fill=fill_color)
draw_object.ellipse((x + w - r, y, x + w, y + r), fill=fill_color)
draw_object.ellipse((x, y + h - r, x + r, y + h), fill=fill_color)
draw_object.ellipse((x + w - r, y + h - r, x + w, y + h), fill=fill_color)
draw_object.rectangle((x + r / 2, y, x + w - (r / 2), y + h), fill=fill_color)
draw_object.rectangle((x, y + r / 2, x + w, y + h - (r / 2)), fill=fill_color)
2.4.2 绘制三角形 (对话的哪个尖尖)
draw_object.polygon([
(bg_height + space_length / 2, bg_height / 2),
(bg_height + space_length, bg_height / 2 - space_length / 2),
(bg_height + space_length, bg_height / 2 + space_length / 2),
], fill="#FFFFFF")
2.4.3 绘制字体
draw_object.text((bg_height + space_length + 15, (bg_height - 25) / 2 - 5 - 1),
text, fill=0, font=ImageFont.truetype(font_path, font_size))
2.5 保存图片
bg_img.save(save_path)
3. 效果展示
4. 成品代码
from PIL import Image, ImageDraw, ImageFont
def get_font_render_size(text, font_path, font_size):
"""
:param text: 文字
:param font_path: 字体路径
:param font_size: 字体大小
:return: tuple 宽高
"""
canvas = Image.new('RGB', (2048, 2048))
ImageDraw.Draw(canvas).text((0, 0),
text, font=ImageFont.truetype(font_path, font_size))
bbox = canvas.getbbox()
return bbox[2] - bbox[0], bbox[3] - bbox[1]
def main(text="Hello World", logo_path="logo.jpg", save_path="save.jpg",
font_path="fonts/msyhl.ttc", font_size=25, space_length=20,
bg_height=64):
# 计算文字渲染后的长度
text_width, text_height = get_font_render_size(text, font_path, font_size)
# 定义背景宽度
bg_width = text_width + space_length
# 生成背景
bg_img = Image.new(mode='RGB', size=(bg_width + 100, bg_height), color="#F5F5F5")
# 读取头像文件,并绘制头像到背景图片
logo = Image.open(logo_path, mode="r")
logo = logo.resize((bg_height, bg_height))
bg_img.paste(logo, (0, 0))
# 绘制气泡
## 1. 绘制圆角矩形
x, y, w, h, r = bg_height + space_length, 0, text_width + space_length * 1.5, bg_height, space_length
fill_color = "#FFFFFF"
draw_object = ImageDraw.Draw(bg_img)
draw_object.ellipse((x, y, x + r, y + r), fill=fill_color)
draw_object.ellipse((x + w - r, y, x + w, y + r), fill=fill_color)
draw_object.ellipse((x, y + h - r, x + r, y + h), fill=fill_color)
draw_object.ellipse((x + w - r, y + h - r, x + w, y + h), fill=fill_color)
draw_object.rectangle((x + r / 2, y, x + w - (r / 2), y + h), fill=fill_color)
draw_object.rectangle((x, y + r / 2, x + w, y + h - (r / 2)), fill=fill_color)
## 2. 绘制三角形 (对话的哪个尖尖)
draw_object.polygon([
(bg_height + space_length / 2, bg_height / 2),
(bg_height + space_length, bg_height / 2 - space_length / 2),
(bg_height + space_length, bg_height / 2 + space_length / 2),
], fill="#FFFFFF")
## 3. 绘制字体
draw_object.text((bg_height + space_length + 15, (bg_height - 25) / 2 - 5 - 1),
text, fill=0, font=ImageFont.truetype(font_path, font_size))
bg_img.save(save_path)
if __name__=="__main__":
main("Hello World") # 更改此处文字即可。