python生成模拟微信气泡图片

news2025/1/16 1:45:50

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") # 更改此处文字即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10245.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【金融项目】尚融宝项目(十三)

25、充值 25.1、需求介绍 25.1.1、投资人充值 **1、需求描述 ** 标的产生后,平台展示标的,投资人就可以在平台投资标的,获取收益;投资人投资标的必须满足以下条件: 充值过程与绑定过程一致,也是在平台发…

Delphi 11.2 Alexandria程序集代码

Delphi 11.2 Alexandria程序集代码 高DPI VCL设计器-VCL设计器现在在设计时使用类似Microsoft Windows的样式,这意味着除非禁用此功能,否则设计器中的控件始终使用此样式绘制。此样式与Windows当前使用的浅色或深色主题相匹配。 编辑器选项卡-在版本11.2…

【3D目标检测】Frustum PointNets for 3D Object Detection from RGB-D Data

目录概述细节网络结构视锥候选框3D实例分割边界框参数回归损失函数概述 首先本文是基于图像和点云的,属于早期的模态融合的成果,是串行的算法,而非并行的,更多的是考虑如何根据图像和点云这两个模态的数据进行3D目标检测。 提出动…

亚马逊平台不给力?来Starday,告诉你什么是真正的高阶玩法

距2021年的亚马逊封号潮已经过去了一段时间,但其影响却依然在跨境电商行业间回荡。从4月份起,亚马逊就开始对违反平台规则的卖家进行封号。此后打击规模持续扩大,到6月中下旬,深圳一批头部卖家均被亚马逊平台下架,遭到…

Coverage-based Greybox Fuzzing as Markov Chain

AFLFast: Coverage-based Greybox Fuzzing as Markov Chain 一、论文阅读 论文来自CCS2016 作者:Marcel Bhme 模糊测试领域巨佬 Abstract 基于覆盖的灰盒模糊测试 Coverage-based Greybox Fuzzing (CGF)。大多数测试用例执行少数高频路径,制定策略倾…

浪潮信息工程师:谈一谈设备透传虚拟机启动慢背后的原因及其优化方法 | 第 51 期

本周「龙蜥大讲堂」预告来啦!龙蜥社区邀请了浪潮信息操作系统研发工程师崔士伟分享《设备透传虚拟机的快速启动优化》,快来扫码入群,预定前排小板凳观看直播吧! 直播主题及内容介绍 直播主题:设备透传虚拟机的快速启…

360+城市空气质量指数-日度数据、良好天数统计(2001-2022年)

360城市空气质量指数-日度数据、良好天数统计(2001-2022年) 城市空气质量指数-日度数据、良好天数统计 1、包括:360个城市 2、时间:2001.1-2022.1月 3、样本量:1371937条 4、数据来源:空气质量在线…

使用Excel 表示汽车、摩托车10年免检时间、非常清晰。

1,汽车摩托车10年内年检问题 根据最新的国家法律: http://www.wenjiang.gov.cn/wjzzw/c152333/2022-09/30/content_66efe4febb8040758f3f079cf0baa310.shtml 搜索了下,找到了成都的规定: 近日,公安部、市场监管总局…

中电海康-中电52所面经

中电海康,中电52所面经中电海康面经一面(电话面)二面(现场面)自我回顾中电海康面经 一面(电话面) Redis的使用和配置多线程的使用,线程池的使用SpringBoot的核心注解和流程AOP IOC …

java项目-第133期ssm物流服务管理平台系统-java毕业设计

java项目-第133期ssm物流服务管理平台系统-毕业设计 【源码请到资源专栏下载】 今天分享的项目是《物流服务管理平台系统》 该项目分为前台和后台。主要分成三个角色:游客、普通管理员、管理员三个角色。 游客就是用户,只要是访问系统前台的用户都可以算…

华为防火墙的四种智能选路方式

FW支持四种智能选路方式,不同的智能选路方式可以满足不同的需求,管理员可以根据设备和网络的实际情况进行选择。 表1 智能选路方式 智能选路方式 定义 根据链路带宽负载分担 FW按照带宽比例将流量分配到各条链路上。带宽大的链路转发较多的流量&…

【我的渲染技术进阶之旅】基于Filament渲染引擎绘制一个不停旋转的彩色矩形

一、绘制三角形回顾 在上一篇博客 【我的渲染技术进阶之旅】Google开源的基于物理的实时渲染引擎Filament源码分析:Android版本的Filament第一个示例:sample-hello-triangle 中,我们分析了如何使用Filament来绘制一个三角形,效果如下所示,有一个不停旋转的彩色三角形: …

“外卷”的羽绒服

【潮汐商业评论/ 原创】 2022年的寒潮要比以往来得更早。 “你能想到我今年的第一件羽绒服竟然是在十一期间买的。”没等上“双十一”的车,Eva在国庆期间就已下单了“秋天的第一件羽绒服”。把保暖战线拉长的也不止Eva一个人,据浙商证券研报显示&#…

SpringBoot原理初探以及第一个SpringBoot程序【SpringBoot】

文章目录一.SpringBoot1.1 Spring和SpringBoot1.2 本阶段学习任务1.3 微服务架构二.搭建一个SpringBoot程序2.1 新建SpringBoot项目(官方)2.2 正常创建SpringBoot项目2.3 项目结构2.4 启动项目2.5 写一个接口HelloControlier2.6 原理2.7 更改配置三.原理…

Plaxis Python 命令流自动化处理、岩土工程渗流问题之有限单元法

目录 岩土工程渗流问题之有限单元法:理论、模块化编程实现、开源程序手把手实操应用 基于python命令流及代码的Plaxis自动化建模与典型案例实践应用 岩土工程渗流问题之有限单元法:理论、模块化编程实现、开源程序手把手实操应用 有限单元法在岩土工程…

NC65 sql server 报数据库“xxx”事务日志已满 的解决方案。

近日公司的NC系统在做薪资发放的计算是,报了如下图的错误: 如何解决解决事务日志已满的问题(SQL Server 错误 9002)这个问题呢? 微软给的方案 适用于: SQL Server(所有受支持的版本&#xf…

IPWorks Encrypt Delphi强加密的一整套组件

IPWorks Encrypt Delphi强加密的一整套组件 通过主要加密标准实现强加密的一整套组件。 IPWorks Encrypt是一个广泛的组件库,允许您通过主要的加密标准(包括S/MIME、OpenPGP、TripleDES、TwoFish、RSA、AES等)对文件、电子邮件、文档和消息进行加密和解密。 IPWorks…

整理了173家国企清单,跳槽必备!

我这里汇总了一些计算机专业可以加入的国企,分享给求职的小伙伴们,内容很多,先收藏再看! 一、首选证券公司 各省基本都有一所证券公司,沿海省份集中在税前30-40万左右,内地集中在20-30万。很少加班&#…

二、使用java简单操作kafka

系列文章目录 1.kafka基本原理 文章目录系列文章目录一、搭建一个kafka的demo2.引入依赖3.创建对应的类二、生产者2-1发送到指定分区,等待消息发送成功(会阻塞)2-2发送到指定分区,异步方式2-3其余两种情况,不指定分区…

如何在 Ubuntu 22.04 上安装 最新版本Wine

过渡到 Linux 的用户的担忧之一是他们是否可以在 Linux 上运行自己喜欢的应用程序。这些范围可以从 Windows 游戏和简单的应用程序软件。值得庆幸的是,Wine 允许用户在 Linux/Unix 系统上运行和执行 Windows 程序。 Wine (“Wine Is Not an Emulator” …