Pillow如何检测所用字体是否包含指定字符的对应字形
Pillow检测字体缺失指定字符字形的实现方案
你可以直接通过Pillow封装的FreeType接口判断字符是否存在对应字形,不需要额外依赖其他第三方库,判断结果准确无误差。
方法1:读取字体字符映射表检测(推荐)
Pillow加载的TrueType/OpenType字体对象底层对接FreeType库,可以直接调用内置方法查询字符的字形索引:如果索引值为0,就代表当前字体没有该字符的对应字形,绘制时会自动 fallback 到.notdef字形(通常显示为?或者空心方块)。
该方法不需要实际绘制内容,提前就能完成判断,性能很高,适合批量文本处理场景。
对应实现代码如下:
from PIL import Image, ImageDraw, ImageFont def is_char_supported(font: ImageFont.FreeTypeFont, char: str) -> bool: # 调用FreeType接口查询字符对应字形索引,返回0即无对应字形 glyph_index = font.font.getcharindex(ord(char)) return glyph_index != 0 image = Image.new("RGB", (100, 100), "white") draw = ImageDraw.Draw(image) font = ImageFont.truetype("unifont_upper-14.0.04.ttf", size=16) target_char = "𒀀" if is_char_supported(font, target_char): draw.text((1, 1), target_char, font=font, fill="black") else: print(f"当前字体缺失字符 {target_char} 的字形,可选择跳过绘制或切换备用字体") # 此处可添加切换备用字体的逻辑 # fallback_font = ImageFont.truetype("对应支持楔形文字的字体文件路径.ttf", size=16) # draw.text((1, 1), target_char, font=fallback_font, fill="black") image.save("cuneiform.png")
方法2:旧版本Pillow兼容方案
如果你使用的Pillow版本低于8.1.0(未暴露getcharindex接口),可以通过比较字符绘制边界的方式判断:当字体不支持某个字符时,调用getbbox返回的边界会和默认.notdef问号的边界一致。该方法存在小概率误判,优先使用第一种方案。
示例判断逻辑:
def is_char_supported_old(font: ImageFont.FreeTypeFont, char: str) -> bool: # 取缺失字符默认显示的?的边界框作为参照 notdef_bbox = font.getbbox("?") char_bbox = font.getbbox(char) # ASCII问号本身直接返回支持 if char == "?": return True return char_bbox != notdef_bbox
注意事项
- 不要通过绘制后识别图像内容的方式判断是否缺字:不同字体的
.notdef字形不统一,有的是问号、有的是空心豆腐块、有的是空白,识别误差很大。 - 处理整段文本时可以逐字符调用检测方法,遇到缺字字符自动切换到提前加载好的备用字体,即可实现多字体自动fallback的排版效果。
内容的提问来源于stack exchange,提问作者Terence Eden
相关产品推荐
相关产品推荐

