前言:
大家好我是最渣的黑客(宋哈哈),今天在写一个小脚本,让文字写到图片中,一个两个标题就可以手工用adobe 的 photoshop 就能解决,但是很多,就显得那么无力,当然也可以用 ps 的 数据组功能 也可以解决问题,但是每次都要打开ps,就显得很麻烦。用Python 去做就是几秒的问题。
我查了很多 优快云 ,还有百度 ,以及google 。很少有人讲 PIL 的文字居中对齐的办法。貌似 PIL 没有自带居中对齐的功能。所以就需要自己去计算一些数值来得到 近似居中 的方法。我找到一篇,但是那边只是讲到了 英文 和中文 如何居中,但是我遇到的都是中文英文数字都有的字符串情况吧。比如:Python基础编程教学第1集 ,这样的标题,既有英文又有数字,还有中文。
下面我就讲下,我是如何把这种类型的字符串如何居中的。下面方法也适合全英文和全中文的。一起的
全部代码如下:
# encoding:utf-8
import os
from PIL import Image, ImageFont, ImageDraw # 导入模块
import re
def generate_img():
file = os.listdir('file_title') # 浏览本地文件标题
for f in file:
filename = str(f).replace('.txt', '')
font_size = 40 # 设置字符串字号 为 40px
font = ImageFont.truetype(r'C:\Windows\Fonts\微软雅黑\msyhbd.ttc',
size=font_size)
font1 = ImageFont.truetype(r'C:\Windows\Fonts\微软雅黑\msyh.ttc',
size=45)
W = 700
H = 700
im = Image.new("RGB", (W, H), "white") # 创建 700*700 的像素
draw = ImageDraw.Draw(im)
match1 = re.findall('[a-zA-Z0-9]+', filename)
match2 = re.findall(u'[\u4e00-\u9fa5]', filename)
en_number = "".join(match1) # 英文和数字
chinese_simplified = "".join(match2) # 中文简体
chinese_simplified_len = len(chinese_simplified) # 计算有多少个中文简体字
en_number_size = draw.textsize(en_number)[0] * 4.5 # 英文和数字长度,因为我设置的字体样式原因,会比默认的英文长度大4.5倍左右,如何计算通过PS 导入每张所得图片计算位置。
chinese_simplified_size = font_size * chinese_simplified_len # 中文长度,前提是背景也是 px 单位。设置一个中文字体为 40号字体等于 宽40p*高40px,在700px*700px所占面积。
total_len = en_number_size + chinese_simplified_size # 英文和中文和数字 全部长度
draw.text(((700 - total_len) / 2, 100), filename, fill=(255, 0, 0), font=font) # 利用ImageDraw的内置函数,在图片上写入文字
print("请输入关于《%s》关键词:" % filename)
for n in range(200,500,100):
title1 = input("请输入第一个关键词:")
title2 = input("请输入第一个关键词:")
draw.text((145, n), title1, fill=(255, 0, 0), font=font1) # 利用ImageDraw的内置函数,在图片上写入文字
draw.text((400, n), title2, fill=(255, 0, 0), font=font1) # 利用ImageDraw的内置函数,在图片上写入文字
# im.show()
im.save(r'D:\pro_py\taobao_aotu\baby_img\%s.jpg' % filename)
if __name__ == '__main__':
generate_img()
1.【下方】代码解释:
导入 PIL 和 re ,os 库,没有安装的需要pip 安装下,或者是 pycharm 设置里面去安装下。一般都是自带。
# encoding:utf-8
import os
from PIL import Image, ImageFont, ImageDraw # 导入模块
import re
2.【下方】代码解释:
用os 库浏览本地文件,因为我这是全是 txt 文件,所有我直接就把它转成 str 然后替换掉了 “.txt” ,注意有个点。这里得到了文件名称。
file = os.listdir('file_title')
for f in file:
filename = str(f).replace('.txt', '')
得到文件名称如下:
30天旅行英语
AutoCAD2017机械设计教程
Python核心编程翻译版
Web安全之信息收集篇
短视频剧本1700条脚本文案
零基础学PHP全彩版
黑客与逆向python之道
3.【下方】代码解释:
创建一个 700*700的白底图片,单位为px 。
W = 700
H = 700
im = Image.new("RGB", (W, H), "white") # 创建 700*700 的像素
draw = ImageDraw.Draw(im)
4.【下方】代码解释:
1)设置字体大小为:40px
2)设置字体样式为:微软雅黑加粗
3)match1 是 正则表达式筛选出 字符串的英文和数字
4)match2 是 正则表达式筛选出 字符串的中文字体
5)en_number 是将筛选出来的 英文和数字 list【列表 】转换成 字符串,方便计算长度
6)en_number 是将筛选出来的 中文字体 list【列表 】转换成 字符串,方便计算长度
font_size = 40 # 设置字符串字号 为 40px
font = ImageFont.truetype(r'C:\Windows\Fonts\微软雅黑\msyhbd.ttc',size=font_size)
match1 = re.findall('[a-zA-Z0-9]+', filename)
match2 = re.findall(u'[\u4e00-\u9fa5]', filename)
en_number = "".join(match1) # 英文和数字
chinese_simplified = "".join(match2) # 中文简体
5.【下方】代码解释【重要的来了】
chinese_simplified_len = len(chinese_simplified) # 计算有多少个中文简体字
en_number_size = draw.textsize(en_number)[0] * 4.5 # 英文和数字长度,因为我设置的字体样式原因,会比默认的英文长度大4.5倍左右,如何计算通过PS 导入每张所得图片计算位置。
chinese_simplified_size = font_size * chinese_simplified_len # 中文长度,前提是背景也是 px 单位。设置一个中文字体为 40号字体等于 宽40p*高40px,在700px*700px所占面积。
total_len = en_number_size + chinese_simplified_size # 英文和中文和数字 全部长度
代码思路【复制代码并不能解决问题,要了解思路】:
因为我们想要我们的字符串,在图片中居中。就需要知道,总字符串的长度 为多少,计算 英文和数字的大小方法为:
draw.textsize(en_number) # en_number 是 英文+数字的字符串,链接上述代码。别看不懂。
因为我们只需要长度(宽),所以取元组的 第一位数值,得到真正的英文和数字的长度为:en_number_size
en_number_size = draw.textsize(en_number)[0]
得到了,英文和数字的长度后,我们需要得到中文字体的长度,而中文实际的长度计算就比较简单了,因为我们默认创建的是 700px * 700px ,而字体大小【font_size】是 40px 。那么就是字体 的宽高就是 40px*40px ,px:像素的意思。所以这里得到一个中文字体的宽为 40px ,代码如下。
chinese_simplified_size = font_size * chinese_simplified_len
其中 chinese_simplified_len 为 有多少个字符,上面可以通过 len 来计算有多少个中文字符,然后乘以 一个字符的宽 的长度,得到中文字符总长度为:chinese_simplified_size, 从而可以计算到 英文和中文的总长度为:total_len
total_len = en_number_size + chinese_simplified_size # 英文和中文和数字 全部长度
由此然后利用简单的数学图形 公式计算下:得到居中的长度: (700 - total_len) / 2 ,得到了左右两边除去 字符串 总长度的长度。
然后进行输入到代码中,以下代码为例:
(700 - total_len) / 2 : 是居中位置
filename : 是文件名称
fill=(255, 0, 0) : 是字体颜色,
font=font : 字体样式
draw.text(((700 - total_len) / 2, 100), filename, fill=(255, 0, 0), font=font)
im.save(r'D:\pro_py\taobao_aotu\baby_img\%s.jpg' % filename)
总结:
可能有人会疑虑,你的计算英文数字这个代码那不是 * 4.5 吗?为什么要 *4.5 ?
en_number_size = draw.textsize(en_number)[0] * 4.5
因为我默认设置的字体是:微软雅黑加粗,会自动的把英文和数字的字体 放大到原来的约等于 4.5倍,所以乘以了 4.5。如何得到 4.5 倍这个数值的呢?
我用的是 adobe AI 把每一次的不同长度 英文和数字的图片导入到了 adobe 的 ai 中进行了,手工的计算。
下图 英文和数字的 字符 一共有 11 个按照 en_number_size = draw.textsize(en_number)[0] ,计算得到为:66 ,但加了 字体样式后总长度为实际长度为 288 ,288/66 ≈ 4.3。 我以此类推,将 字符数量 从 4 个 5个 6个 12个 这样计算,差不多取出中间值为 4.5 。也就是说加了字体样式后,字体会扩大 4.5 倍的长度。所以我再那里 * 4.5 。
**温馨提醒:**你所设置的 字体类型,字体样式 加粗 还是 加描边 等都会影响,居中的实际长度。建议您,其他代码保持不变,用手工计算出加样式后和不加的倍数,直接 换掉 4.5 就行。
也有可能会有更好的居中方法,此方法仅供参考。如果对你有帮忙,帮忙点个关注呗。我会持续分享优快云 ,解决办法少,有很小众的问题。