Python Pillow加载ttf字体在图片上写字教程
本教程详细讲解在 Python 中使用 Pillow 库加载 TTF/OTF 矢量字体并在图片上绘制中文文字的完整方法,包含环境准备、标准调用链路、坐标与 anchor 对齐机制、长文本换行与常见问题排查。
PIL.ImageFont.truetype(font, size) 加载外部 TTF 或 OTF 矢量字体文件,再结合 ImageDraw.Draw.text() 进行栅格化渲染。本文提供可立即执行的完整步骤、坐标度量技巧及常见排坑说明。
一、准备工作与环境依赖
Pillow 是 Python 原生图像处理库 PIL 的现代分支。处理文字需要依赖系统已构建好的 FreeType 字体引擎支持。通常通过标准包管理器安装的 Pillow 预编译轮子(Wheels)已默认静态编译包含 FreeType 模块,无需手动安装底层 C 库。
执行验证命令确认模块安装正常:
准备一个可用的中文字体文件(.ttf 或 .otf)。如果是在 Windows 环境下,系统目录 C:/Windows/Fonts/msyh.ttc(微软雅黑)或 simhei.ttf(黑体)可直接作为字体路径;在 Linux 或跨平台服务器端,建议将字体文件(例如开源免费商用的“阿里巴巴普惠体”或“思源黑体”)与代码存放在同一工程目录中。
二、核心操作流程与标准代码
向图片写入文字的标准生命周期包含 5 个明确步骤:建立画布对象、载入 TTF 字体规格、实例化绘图图层、测定排版边界、执行文字像素栅格化并写出。
以下为完整的端到端示范脚本。脚本将在内存中新建一张暖灰底色的画布,加载指定 TTF 字体并写入标题及正文:
图像生成完毕,保存至: output_pillow_text.png
打开生成的图片后,即可看到清晰无锯齿的中文文字整齐排列在设定坐标处。
三、排版控制:文本边界测距与 Anchor 锚点对齐
在实际生产场景中(如自动生成宣发海报、照片打水印或生成证书),文字往往需要居中、居右或在限定宽度内排版,直接写死绝对坐标会导致不同长度的文字位置偏移。
1. 使用 textbbox 准确计算文字宽高
在较早的 Pillow 版本中,开发者习惯使用 draw.textsize() 或 font.getsize()。从 Pillow 10.0.0 起,这些旧接口已被正式移除,统一采用 draw.textbbox()。该方法接收起始参考坐标、文本及字体对象,返回一个四元组 (left, top, right, bottom):
2. 使用 anchor 参数一行代码实现对齐
Pillow 内部提供了 anchor(锚点)机制。参数由两个英文字母组成:第一个代表水平对齐(l=左, m=居中, r=右),第二个代表垂直对齐(a=升部顶端, m=垂直居中, b=降部底端, s=基线)。
若要将文字精准放置在画布的正中心点 (width // 2, height // 2),无需人工测算宽高做减法,只需指定 anchor="mm":
四、方案对比:ImageFont 两种载入模式的关键差异
初学者在使用 Pillow 时常疑惑为什么存在 load_default() 和 truetype() 两种获取字体的方式。下表对比了两者的本质技术特征与能力范围:
| 对比维度 | ImageFont.load_default() | ImageFont.truetype(font, size) |
|---|---|---|
| 字符编码覆盖 | 仅包含基础 ASCII 字符,中文全部输出为空格或乱码问号 | 完整支持 Unicode/CJK 汉字、标点与日韩等多国语言 |
| 字号无级缩放 | 固定位图点阵尺寸(约 10px),无法任意放大或缩小 | 无级矢量缩放,从 8px 到 1000px 均保持矢量平滑 |
| 边缘渲染质量 | 点阵硬边缘,带有明显颗粒感和锯齿 | 基于 FreeType 子像素平滑渲染,抗锯齿过渡柔和自然 |
| 外部资源依赖 | 无任何外部依赖,Pillow 内部硬编码集成 | 必须指定系统或本地存在的物理 TTF/OTF 文件路径 |
差异的关键在于:load_default() 的设计定位是无环境依赖下的代码测试占位,而任何包含非英文字符或具有视觉要求的图形合成任务,都必须使用 truetype()。
五、生产实践与长文本自动折行
Pillow 的底层渲染引擎将换行符(
)视作换行依据,但它不会自动根据图片宽度进行段落自动换行。如果传入的一行文本过长,超出图片边界的部分将直接被截断。
在批量处理业务文案时,需要编写一个轻量级的文本切分函数,利用 font.getlength() 逐字计算宽度,在达到最大宽度上限时主动切行:
六、高频报错与排坑清单
加载 TTF 字体操作涉及操作系统文件系统访问、字体字形表解析与图像混合,在工程化部署中容易遇到以下典型问题:
-
报错
OSError: cannot open resource:
原因:Pillow 无法在指定路径找到该字体文件。请避免使用不稳定的相对路径(如直接写"font.ttf"),推荐使用os.path.join(os.path.dirname(__file__), "fonts/myfont.ttf")构建绝对路径,并在载入前通过os.path.isfile()确认文件存在。 -
中文字符显示为白色方块(“豆腐块” □):
原因:加载的字体文件中缺少中文字符的字形轮廓(Glyph)。例如西方系统自带的arial.ttf或times.ttf仅包含西文字符,遇到汉字时没有对应点阵或贝塞尔数据,FreeType 只能以未定义方块代替。解决办法是明确引入涵盖 GB2312/GBK 或通用中文字库的字体文件。 -
批量产图性能迟缓:
原因:在批量循环(例如处理上万张图片)中,每次迭代都重复执行ImageFont.truetype()。解析 TTF 二进制字形表存在磁盘 I/O 与内存解析成本,应在循环体外部预先完成字体实例加载,循环内部复用同一font实例。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













