我正在创作中国篆书的图像。我为此任务准备了三种真字体(Jin_Wen_Da_Zhuan_Ti.7z、Zhong_Guo_Long_Jin_Shi_Zhuan.7z、Zhong_Yan_Yuan_Jin_Wen.7z,仅用于测试目的)。以下是 Microsoft Word 中的外观
汉字“我”(I/me)。这是我的 Python 脚本:
import numpy as np
from PIL import Image, ImageFont, ImageDraw, ImageChops
import itertools
import os
def grey2binary(grey, white_value=1):
grey[np.where(grey <= 127)] = 0
grey[np.where(grey > 127)] = white_value
return grey
def create_testing_images(characters,
font_path,
save_to_folder,
sub_folder=None,
image_size=64):
font_size = image_size * 2
if sub_folder is None:
sub_folder = os.path.split(font_path)[-1]
sub_folder = os.path.splitext(sub_folder)[0]
sub_folder_full = os.path.join(save_to_folder, sub_folder)
if not os.path.exists(sub_folder_full):
os.mkdir(sub_folder_full)
font = ImageFont.truetype(font_path,font_size)
bg = Image.new('L',(font_size,font_size),'white')
for char in characters:
img = Image.new('L',(font_size,font_size),'white')
draw = ImageDraw.Draw(img)
draw.text((0,0), text=char, font=font)
diff = ImageChops.difference(img, bg)
bbox = diff.getbbox()
if bbox:
img = img.crop(bbox)
img = img.resize((image_size, image_size), resample=Image.BILINEAR)
img_array = np.array(img)
img_array = grey2binary(img_array, white_value=255)
edge_top = img_array[0, range(image_size)]
edge_left = img_array[range(image_size), 0]
edge_bottom = img_array[image_size - 1, range(image_size)]
edge_right = img_array[range(image_size), image_size - 1]
criterion = sum(itertools.chain(edge_top, edge_left,
edge_bottom, edge_right))
if criteria > 255 * image_size * 2:
img = Image.fromarray(np.uint8(img_array))
img.save(os.path.join(sub_folder_full, char) + '.gif')
核心片段在哪里
font = ImageFont.truetype(font_path,font_size)
img = Image.new('L',(font_size,font_size),'white')
draw = ImageDraw.Draw(img)
draw.text((0,0), text=char, font=font)
例如,如果您将这些字体放在文件夹./fonts
中,并使用
create_testing_images(['我'], 'fonts/金文大篆体.ttf', save_to_folder='test')
该脚本将./test/金文大篆体/我.gif
在您的文件系统中创建。
现在的问题是,虽然它适用于第一种字体金文大篆体.ttf(在 Jin_Wen_Da_Zhuan_Ti.7z 中),但该脚本不适用于其他两种字体,即使它们可以在 Microsoft Word 中正确呈现:for 中国龙金石篆.ttf(Zhong_Guo_Long_Jin_Shi_Zhuan.7z),它什么bbox
都不会画None
;对于中研院金文.ttf(在Zhong_Yan_Yuan_Jin_Wen.7z),它会在图片中画一个没有字符的黑框。
因此未能通过 的测试criterion
,其目的是测试全黑输出。我用FontForge查看了字体的属性,发现第一个字体金文大篆体.ttf(在Jin_Wen_Da_Zhuan_Ti.7z中)使用的是UnicodeBmp
而另外两个使用 Big5hkscs
实际上,我也尝试通过尝试获取具有混乱字体名称的字体来解决此问题。pycairo
我在安装这些字体后尝试过:
import cairo
# adapted from
# http://heuristically.wordpress.com/2011/01/31/pycairo-hello-world/
# setup a place to draw
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
ctx = cairo.Context (surface)
# paint background
ctx.set_source_rgb(1, 1, 1)
ctx.rectangle(0, 0, 100, 100)
ctx.fill()
# draw text
ctx.select_font_face('金文大篆体')
ctx.set_font_size(80)
ctx.move_to(12,80)
ctx.set_source_rgb(0, 0, 0)
ctx.show_text('我')
# finish up
ctx.stroke() # commit to surface
surface.write_to_png('我.gif')
这同样适用于金文大篆体.ttf(在 Jin_Wen_Da_Zhuan_Ti.7z 中):
但仍然没有和其他人在一起。例如:(ctx.select_font_face('中國龍金石篆')
报告_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW
)和ctx.select_font_face('¤¤°êÀsª÷¥Û½f')
(使用默认字体绘制)都不起作用。(后一个名字就是上图字体查看器中显示的乱码,通过一行Mathematica代码得到,ToCharacterCode["中國龍金石篆", "CP950"] // FromCharacterCode
这里CP950
是Big5的代码页。)
所以我想我已经尽力解决这个问题,但仍然无法解决。我还提出了其他方法,例如使用 FontForge 重命名字体名称或将系统编码更改为 Big5,但我仍然更喜欢仅涉及 Python 的解决方案,因此用户需要较少的额外操作。任何提示将不胜感激。谢谢你。
致stackoverflow版主:这个问题乍一看似乎“过于本地化”,但它可能发生在其他语言/其他编码/其他字体中,解决方案可以推广到其他情况,所以请不要关闭它有了这个原因。谢谢你。
更新:奇怪的 Mathematica 可以识别 CP936 中的字体名称(GBK,可以认为是我的系统编码)。以中国龙金石篆.ttf(Zhong_Guo_Long_Jin_Shi_Zhuan.7z)为例:
但是设置ctx.select_font_face('ÖÐøý½ðʯ*')
也不起作用,这将使用默认字体创建字符图像。