Python学习
【小白学Python】自定义图片的生成(一)
目录
- 1. 文件内容
- 2.生成图片规则
- 3. 修改代码
- 2.1 尝试一行汉字展示
- 3.1 读取txt文件
- 3.2 解决文字过长问题
- 3.3 删减指定文字
- 4. 总结
1. 文件内容
正如上篇文章所说,我需要读取txt文件的文字内容,将文字内容填充到图片上,按照一定规则生成多个图片。
文件大致内容如下
2.生成图片规则
txt是之前从zhihu问答模块尝试爬取的,可以看出来,上述文字是以问答形式呈现的,生成图片规则有两个:
- 每个QA的文字单独一张图片,Q一行,A一行。
- 去掉**@之后,:**之前的文字。
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, 900
image = 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) / 2
y = (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:
break
end_index = s.find(end, start_index + len(start))
if end_index == -1:
break
s = 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:
break
end_index = s.find(end, start_index + len(start))
if end_index == -1:
break
s = s[:start_index] + s[end_index + len(end):]
return s
def draw_text(text):
text = remove_between_chars(text, '@', ':')
# 设置图片大小
width, height = 600, 900
image = 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) / 2
y = (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.5
draw.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文件的功能和图片生成的功能结合起来,自动爬取,自动生成,再长远点自动发布到指定平台。