当前位置: 首页 > news >正文

【小白学Python】自定义图片的生成(二)

Python学习
【小白学Python】自定义图片的生成(一)

目录

    • 1. 文件内容
    • 2.生成图片规则
    • 3. 修改代码
      • 2.1 尝试一行汉字展示
      • 3.1 读取txt文件
      • 3.2 解决文字过长问题
      • 3.3 删减指定文字
    • 4. 总结

1. 文件内容

正如上篇文章所说,我需要读取txt文件的文字内容,将文字内容填充到图片上,按照一定规则生成多个图片。
文件大致内容如下
在这里插入图片描述

2.生成图片规则

txt是之前从zhihu问答模块尝试爬取的,可以看出来,上述文字是以问答形式呈现的,生成图片规则有两个:

  1. 每个QA的文字单独一张图片Q一行,A一行
  2. 去掉**@之后,:**之前的文字。

3. 修改代码

上一篇的完整代码如下

from PIL import Image, ImageDraw, ImageFont# 设置图片大小
width, height = 800, 800
image = Image.new('RGB', (width, height), color='black')# 设置文字
text = "123456"# 加载字体文件,并设置字体大小
# 注意:确保arial.ttf字体文件路径是正确的
font = ImageFont.truetype('C:\\Windows\\Fonts\\arial.ttf', 60)
# font.color = 'yellow'
# 创建画布
draw = ImageDraw.Draw(image)# 使用draw的textsize方法获取文本大小
text_width, text_height = draw.textsize(text, font=font)# 计算文字位置,使其居中
x = (width - text_width) / 2
y = (height - text_height) / 2# 绘制文字
draw.text((x, y), text, font=font, fill='white')# 保存图片
image.save('text_image.png')

2.1 尝试一行汉字展示

替换代码如下
在这里插入图片描述
执行main.py,查看生成的图片,有问题,乱码了。
在这里插入图片描述

搜索后发现是字体使用的不兼容,更换字体为simhei.ttf,图片文字正常展示。
调整图片长宽为 width, height = 600, 900,文字位置为

x = (width - text_width) / 2
y = (height - text_height) / 3.5

执行main.py,目前看起来运作一切良好。
在这里插入图片描述

3.1 读取txt文件

为了读取指定的txt文件,我们对上述代码做了如下改动

  • 使用file.readlines()一次性读入所有txt内容,大文件需要注意,内存可能会爆
  • 根据文件内容,每4行拼接一次text,并生成一个图片
  • 将生成图片的逻辑拆分,新增drawText(text函数
from PIL import Image, ImageDraw, ImageFont# 打开txt文件,将txt文件内容读入内存
# !!!如果文件过大,最好不要直接这么写
with open('QA.txt', 'r', encoding='utf-8') as file:lines = file.readlines()text = ''def drawText(text):# 设置图片大小width, height = 600, 900image = Image.new('RGB', (width, height), color='black')# 加载字体文件,并设置字体大小# 注意:确保arial.ttf字体文件路径是正确的font = ImageFont.truetype('C:\\Windows\\Fonts\\simhei.ttf', 20)# font.color = 'yellow'# 创建画布draw = ImageDraw.Draw(image)# 使用draw的textsize方法获取文本大小text_width, text_height = draw.textsize(text, font=font)if text_width > width + 10:font.size = font.size - 1# 计算文字位置,使其居中x = (width - text_width) / 2y = (height - text_height) / 3.5# 绘制文字draw.text((x, y), text, font=font, fill='white')# 保存图片image.save('pics/text_image_' + index.__str__() + '.png')for index in range(len(lines)):#根据txt文件内容 每4行生成一张图片if index == 0 or index % 4 != 0:text = text + lines[index]#如果是txt结尾了,直接生成图片if index + 1 == len(lines):drawText(text)else:text = text + lines[index]drawText(text)# 将拼接的字符初始化text = ''

上述生成的逻辑满足了每个QA都是单独的图片,但是如果QA文字过多的话,图片中的文字会超过图片边界,无法正常展示
在这里插入图片描述

3.2 解决文字过长问题

draw.text绘制文字的函数并没有设置自动换行的功能,貌似只能根据图片的width来计算文字的长度,再尝试换行。

在这里插入图片描述
经过简单调试,采用往字符串中添加换行符\n的形式,这样图片绘制文字时可自动换行。
我这里处理的比较简单,固定的添加位置,很长的文字也只换行一次,但目前我的txt文件暂时可以用这种方式。

在这里插入图片描述

3.3 删减指定文字

由于txt文件是从zhihu爬取的,回答的时候会带上作者的名字,我想把这些文字去掉

在这里插入图片描述
在这里插入图片描述
新增如下删减函数

def remove_between_chars(s, start, end):while True:start_index = s.find(start)if start_index == -1:breakend_index = s.find(end, start_index + len(start))if end_index == -1:breaks = s[:start_index] + s[end_index + len(end):]return s

在这里插入图片描述
在这里插入图片描述

4. 总结

我的目标是将txt文件中的文字,按照一定规则绘制在图片上,当前的实现效果马马虎虎。

暂时的完整代码如下:

from PIL import Image, ImageDraw, ImageFont# 打开txt文件,将txt文件内容读入内存
# !!!如果文件过大,最好不要直接这么写
with open('QA.txt', 'r', encoding='utf-8') as file:lines = file.readlines()text = ''def remove_between_chars(s, start, end):while True:start_index = s.find(start)if start_index == -1:breakend_index = s.find(end, start_index + len(start))if end_index == -1:breaks = s[:start_index] + s[end_index + len(end):]return sdef draw_text(text):text = remove_between_chars(text, '@', ':')# 设置图片大小width, height = 600, 900image = Image.new('RGB', (width, height), color='black')# 加载字体文件,并设置字体大小# 注意:确保arial.ttf字体文件路径是正确的font = ImageFont.truetype('C:\\Windows\\Fonts\\simhei.ttf', 20)# font.color = 'yellow'# 创建画布draw = ImageDraw.Draw(image)# 使用draw的textsize方法获取文本大小text_width, text_height = draw.textsize(text, font=font)# 计算文字位置,使其居中x = (width - text_width) / 2y = (height - text_height) / 3.5# 此处简单处理 如果将要到达边界,往字符串指定位置增加换行符# 这里经过调试,我这里使用22比较合适,后续需要优化if text_width > width - 10:new_text = text[:22] + "\n\n     " + text[22:]# 绘制文字x = (width - text_width // 2) / 2.5draw.text((x, y), new_text, font=font, fill='white')else:# 绘制文字draw.text((x, y), text, font=font, fill='white')# 保存图片image.save('pics/text_image_' + index.__str__() + '.png')for index in range(len(lines)):# 根据txt文件内容 每4行生成一张图片if index == 0 or index % 4 != 0:text = text + lines[index]# 如果是txt结尾了,直接生成图片if index + 1 == len(lines):draw_text(text)else:text = text + lines[index]draw_text(text)# 将拼接的字符初始化text = ''

我对python掌握的比较浅显,编写代码还不太流畅,要花费不少时间用来补充基础知识,代码有很多优化是必要,上述代码的书写毫无美感可言,无论是逻辑还是简单的规范,都有很大提升的必要。

下一步的计划,除了学习python和优化代码之外,将爬取txt文件的功能和图片生成的功能结合起来,自动爬取自动生成,再长远点自动发布到指定平台

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 用Python绘制yolo训练结果比较图-论文需要
  • 鸿蒙轻内核A核源码分析系列六 MMU协处理器(1)
  • 【稳定检索/投稿优惠】2024年智慧金融与财务管理国际会议(SFFM 2024)
  • C#操作MySQL从入门到精通(21)——删除数据
  • C# 设置PDF表单不可编辑、或提取PDF表单数据
  • 开发TEE的踩坑之配置PCCS
  • 子域名爆破工具
  • 拜托:不要像鲍勃大叔那样重构
  • eNSP学习——RIP路由协议的汇总
  • DP:回文串模型
  • 【数据结构】利用单链表再实现通讯录
  • 编程的作品怎么删除编程库:一步步的深入解析
  • 2. Revit API UI 之 IExternalCommand 和 IExternalApplication
  • c++中main(int argc, char* argv[])参数详解
  • PaddleDetection快速体验quick_start
  • EOS是什么
  • JavaScript设计模式之工厂模式
  • leetcode388. Longest Absolute File Path
  • 闭包--闭包作用之保存(一)
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 多线程 start 和 run 方法到底有什么区别?
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • ------- 计算机网络基础
  • 前端性能优化——回流与重绘
  • 如何设计一个比特币钱包服务
  • 深入浏览器事件循环的本质
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 一个项目push到多个远程Git仓库
  • 阿里云ACE认证之理解CDN技术
  • ​ssh免密码登录设置及问题总结
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • # include “ “ 和 # include < >两者的区别
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #WEB前端(HTML属性)
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • #在 README.md 中生成项目目录结构
  • (1)SpringCloud 整合Python
  • (16)Reactor的测试——响应式Spring的道法术器
  • (4) PIVOT 和 UPIVOT 的使用
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (function(){})()的分步解析
  • (pojstep1.3.1)1017(构造法模拟)
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (转)shell中括号的特殊用法 linux if多条件判断
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • (转)视频码率,帧率和分辨率的联系与区别
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .Net Memory Profiler的使用举例
  • .net流程开发平台的一些难点(1)
  • ::前边啥也没有
  • @SuppressLint(NewApi)和@TargetApi()的区别