unable to read font / 文字显示成方框
两个表现,同一个原因。如何列出可用字体、在精简 Docker 镜像里安装字体,以及让中日韩文、阿拉伯文和 emoji 正常渲染。
convert: unable to read font 'Helvetica' @ error/annotate.c/RenderFreetype/1662
或者文字渲染出来了,但每个字符都是空心方框:□□□□
第一步:ImageMagick 认识哪些字体
magick -list font
这会打印它能按名字解析的所有字体,以及每个字体文件的路径。
情况 A —— 列表是空的或很短
机器上没装字体,或者 ImageMagick 编译时没带 fontconfig。精简 Docker 镜像里极其常见,它们根本不带任何字体。
apt install fonts-dejavu-core # Debian / Ubuntu,体积小、覆盖不错
dnf install dejavu-sans-fonts # Fedora
apk add font-dejavu # Alpine
装完再跑一次 magick -list font。如果磁盘上明明有字体文件但列表还是空的,说明缺 fontconfig:
apt install fontconfig && fc-cache -f
绕过字体名解析
你随时可以直接传字体文件的完整路径,跳过名字解析这一步:
magick in.jpg -font /usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf \
-pointsize 48 -fill white -gravity south -annotate +0+30 'Hello' out.jpg
这是脚本和容器里最可靠的写法 —— 不依赖 fontconfig 的判断。
情况 B —— 文字显示成方框
字体加载是成功的,只是它没有你要的那些字符的字形。标准拉丁字体不覆盖中文、日文、韩文、阿拉伯文、希伯来文、泰文、天城文和 emoji。
apt install fonts-noto-cjk # 中日韩
apt install fonts-noto-color-emoji # emoji
apt install fonts-noto # 广泛的 Unicode 覆盖
magick in.jpg \
-font /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc \
-pointsize 48 -fill white -gravity south -annotate +0+40 '你好世界' out.jpg
找到覆盖你文字的字体
fc-list :lang=zh # 覆盖中文的字体
fc-list :lang=ar # 阿拉伯文
fc-match 'Noto Sans CJK SC' # 把名字解析成文件路径
编码
如果非 ASCII 文字出来的是乱码而不是方框,那是编码问题不是字体问题:
magick in.jpg -encoding UTF-8 -font NotoSansCJK-Regular \
-pointsize 40 -annotate +20+60 '你好' out.jpg
同时确认你的终端在用 UTF-8;Windows 上需要 chcp 65001 设置代码页。文字很长或者很难打的话,从文件读入更稳:
magick in.jpg -font NotoSansCJK-Regular -pointsize 40 \
-annotate +20+60 '@caption.txt' out.jpg
从右往左的文字
ImageMagick 不做完整的双向文本整形。阿拉伯文和希伯来文可能出现字母不连写或顺序错误。需要正确整形的话用 Pango 渲染 —— ImageMagick 可以把它当作图源:
magick -background none pango:'<span font="Noto Sans Arabic 40">مرحبا</span>' out.png
先用 magick -list format | grep -i pango 确认,因为不是每个版本都编译了它。