python生成模拟微信气泡图片

0. 起因

众所周知,借刀杀人最为致命,聊天也是如此。

最近我的群聊画风逐渐变味:

在这里插入图片描述

当然,这种图片的生产成本很低,只需在设置页关闭昵称显示,把聊天背景重置为灰色,然后利用截图工具截图,最后保存到手机里,添加到表情包库中即可。

然而微信头像是会更改的,人的精力也是有限的,经过了两天的狂欢后,我们逐渐意识到这种文化的短期性。

但是,无所谓,我会出手!我灵光一闪,只要把数据来源从截图变成生成,那么即使微信头像更改,也可以随时替换,如此,便有了此文。

1. 准备工作

技术栈:Python内置的 PIL(Pillow)库

头像文件:可以直接从微信中保存,我们给它命名为 logo.jpg

主脚本文件:main.py

(为了方便脚本编写,main.pylogo.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") # 更改此处文字即可。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

okfang616

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值