ImageMagick 与中文渲染问题

为什么 convert 和 montage 命令中使用的汉字都没能正确渲染在图片中去呢?
或许可以将本文中的中文替换成 non-ascii 字符,或者 Unicode 字符。

参考了实在是太多文档,都没来得及记下来,只是从 Shell 的历史纪录中翻出来这些命令,做一个记录。

结论

字体问题,必须选择包含中文字形的字体,使用完整的字体名称,比如:Noto-Sans-Mono-CJK-SC-Regular

正常(英文)

convert ~/Pictures/ICON/chrome.jpg -geometry 800x480 sixel:-
montage ~/Pictures/ICON/chrome.jpg jpg:-
montage -label Chrome ~/Pictures/ICON/chrome.jpg /tmp/test.jpg

不正常(中文)

montage -label 谷歌浏览器 ~/Pictures/ICON/chrome.jpg /tmp/test.jpg
montage -label 谷歌浏览器 -font ubuntu-mono ~/Pictures/ICON/chrome.jpg /tmp/test.jpg
montage -label 谷歌浏览器 -font ubuntu-mono -encoding Unicode ~/Pictures/ICON/chrome.jpg /tmp/test.jpg
# 还在文档中发现 label 可以使用各种占位符

convert -draw 'text 10,10 "Hello 谷歌浏览器' ~/Pictures/ICON/chrome.jpg /tmp/test.jpg
convert -draw 'text 10,10 "Hello 谷歌浏览器' -font ubuntu-mono -encoding Unicode ~/Pictures/ICON/chrome.jpg /tmp/test.jpg
convert -background lightblue -fill blue -size 165X270 -pointsize 24 -gravity center -font ubuntu-mono label:'Hello 世界' /tmp/test.jpg
convert -fill red -size 512x50 -pointsize 24 -gravity southeast -font ubuntu-mono -encoding unicode xc:gray -draw "text 20,5 'Hello 世界'" /tmp/test.jpg
convert -debug all -size 300x300 xc:white -font ubuntu-mono label:G /tmp/test.jpg
convert -debug all -size 300x300 xc:white -font ubuntu-mono label:⌘ /tmp/test.jpg
# 还发现了 -debug all,-debug annotate 调试

convert -list configure
identify -list configure
monotage -list configure

解决过程

翻了好多文档,走了好多弯路。
怀疑过编码问题,怀疑过字体问题,但是切换过字符编码,切换过多种字体之后,发现都没用,然后又走回头路。

fc-list
fc-match "Ubuntu"
# Ubuntu-R.ttf: "Ubuntu" "Regular"
fc-match "Ubuntu Mono"
# UbuntuMono-R.ttf: "Ubuntu Mono" "Regular"

总之不停的尝试。

最后,又怀疑 TMD ImageMagick 根本就只支持 ASCII。
然后,发现似乎不是这样,因为看到别个有实现输出 Unicode 字符。

在我将要放弃的时候,在 StackOverflow 看到有人用了个这个方法测试字体,我试了一下,果然有用。

for i in $(convert -list font | grep Font | awk '{print $2}'); do echo $i; convert -font $i -pointsize 36 label:汉 /tmp/fonttest-${i}.jpg; done;

在文件管理器中可以查看到,支持的字体并不多。Ubuntu 自带字体中,只有以下字体可以用来渲染中文:

  • AR-PL-*
  • Droid-Sans-Fallback
  • Note-Sans-*
  • Note-Serif-*
fc-list | grep -E "Droid|Ubuntu" | awk -F: '{print $1}' | xargs ls -lh 
# -rw-r--r-- 1 root root 3.9M 2016-02-13 18:32:57 /usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf
# -rw-r--r-- 1 root root 349K 2015-07-10 20:03:49 /usr/share/fonts/truetype/ubuntu/Ubuntu-BI.ttf
# -rw-r--r-- 1 root root 326K 2015-07-10 20:03:16 /usr/share/fonts/truetype/ubuntu/Ubuntu-B.ttf
# -rw-r--r-- 1 root root 343K 2015-07-10 20:04:01 /usr/share/fonts/truetype/ubuntu/Ubuntu-C.ttf
# -rw-r--r-- 1 root root 401K 2015-07-10 20:04:29 /usr/share/fonts/truetype/ubuntu/Ubuntu-LI.ttf
# -rw-r--r-- 1 root root 406K 2015-07-10 20:04:15 /usr/share/fonts/truetype/ubuntu/Ubuntu-L.ttf
# -rw-r--r-- 1 root root 359K 2015-07-10 20:05:03 /usr/share/fonts/truetype/ubuntu/Ubuntu-MI.ttf
# -rw-r--r-- 1 root root 212K 2011-09-26 23:51:54 /usr/share/fonts/truetype/ubuntu/UbuntuMono-BI.ttf
# -rw-r--r-- 1 root root 187K 2011-09-26 23:51:27 /usr/share/fonts/truetype/ubuntu/UbuntuMono-B.ttf
# -rw-r--r-- 1 root root 206K 2011-09-26 23:51:02 /usr/share/fonts/truetype/ubuntu/UbuntuMono-RI.ttf
# -rw-r--r-- 1 root root 201K 2011-09-26 23:50:35 /usr/share/fonts/truetype/ubuntu/UbuntuMono-R.ttf
# -rw-r--r-- 1 root root 334K 2015-07-10 20:04:45 /usr/share/fonts/truetype/ubuntu/Ubuntu-M.ttf
# -rw-r--r-- 1 root root 378K 2015-07-10 20:05:42 /usr/share/fonts/truetype/ubuntu/Ubuntu-RI.ttf
# -rw-r--r-- 1 root root 346K 2015-07-10 20:05:29 /usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf

这个 10 倍的差距,应该就是原因了。
具体原理我不愿深究,总之找到了支持的字体,后面的操作就顺利了。