- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在创建中文图像 seal script .我为此任务准备了三种真字体( 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 中正确呈现:对于中国龙金石篆.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 code ToCharacterCode["中国龙金石篆", "CP950"]//FromCharacterCode
其中CP950
是Big5的代码页。)
所以我想我已经尽力解决这个问题,但仍然无法解决。我还提出了其他方法,例如使用 FontForge 重命名字体名称或将系统编码更改为 Big5,但我仍然更喜欢仅涉及 Python 的解决方案,因此用户需要较少的额外操作。任何提示将不胜感激。谢谢。
致stackoverflow的版主:这个问题乍一看可能看起来“过于本地化”,但它可能发生在其他语言/其他编码/其他字体中,解决方案可以概括为其他情况,请勿以此理由关闭。谢谢。
更新:奇怪的是 Mathematica 可以识别 CP936 中的字体名称(GBK,可以认为是我的系统编码)。以中国龙金石篆.ttf(Zhong_Guo_Long_Jin_Shi_Zhuan.7z)为例:
但是设置 ctx.select_font_face('ÖÐøý½ðʯ*')
也不起作用,这将使用默认字体创建字符图像。
最佳答案
Silvia 对 OP 的评论...
You might want to consider specifying the
encoding
parameter likeImageFont.truetype(font_path,font_size,encoding="big5")
...让您走到一半,但如果您不使用 Unicode 字体,您似乎还必须手动翻译 Unicode 字符。
对于使用“big5hkscs”编码的字体,我必须这样做......
>>> u = u'\u6211' # Unicode for 我
>>> u.encode('big5hkscs')
'\xa7\xda'
...然后使用 u'\ua7da'
得到正确的字形,这有点奇怪,但它看起来是向 PIL 传递多字节字符的唯一方法。
以下代码适用于我在 Python 2.7.4 和 Python 3.3.1 上使用 PIL 1.1.7...
from PIL import Image, ImageDraw, ImageFont
# Declare font files and encodings
FONT1 = ('Jin_Wen_Da_Zhuan_Ti.ttf', 'unicode')
FONT2 = ('Zhong_Guo_Long_Jin_Shi_Zhuan.ttf', 'big5hkscs')
FONT3 = ('Zhong_Yan_Yuan_Jin_Wen.ttf', 'big5hkscs')
# Declare a mapping from encodings used by str.encode() to encodings used by
# the FreeType library
ENCODING_MAP = {'unicode': 'unic',
'big5': 'big5',
'big5hkscs': 'big5',
'shift-jis': 'sjis'}
# The glyphs we want to draw
GLYPHS = ((FONT1, u'\u6211'),
(FONT2, u'\u6211'),
(FONT3, u'\u6211'),
(FONT3, u'\u66ce'),
(FONT2, u'\u4e36'))
# Returns PIL Image object
def draw_glyph(font_file, font_encoding, unicode_char, glyph_size=128):
# Translate unicode string if necessary
if font_encoding != 'unicode':
mb_string = unicode_char.encode(font_encoding)
try:
# Try using Python 2.x's unichr
unicode_char = unichr(ord(mb_string[0]) << 8 | ord(mb_string[1]))
except NameError:
# Use Python 3.x-compatible code
unicode_char = chr(mb_string[0] << 8 | mb_string[1])
# Load font using mapped encoding
font = ImageFont.truetype(font_file, glyph_size, encoding=ENCODING_MAP[font_encoding])
# Now draw the glyph
img = Image.new('L', (glyph_size, glyph_size), 'white')
draw = ImageDraw.Draw(img)
draw.text((0, 0), text=unicode_char, font=font)
return img
# Save an image for each glyph we want to draw
for (font_file, font_encoding), unicode_char in GLYPHS:
img = draw_glyph(font_file, font_encoding, unicode_char)
filename = '%s-%s.png' % (font_file, hex(ord(unicode_char)))
img.save(filename)
请注意,我将字体文件重命名为与 7zip 文件相同的名称。我尽量避免在代码示例中使用非 ASCII 字符,因为它们有时会在复制/粘贴时搞砸。
这个例子应该适用于 ENCODING_MAP
中声明的类型,如果需要可以扩展(参见 FreeType encoding strings 了解有效的 FreeType 编码),但您需要更改一些Python str.encode()
不产生长度为 2 的多字节字符串时的代码。
更新
If the problem is in the ttf file, how could you find the answer in the PIL and FreeType source code? Above, you seem to be saying PIL is to blame, but why should one have to pass unicode_char.encode(...).decode(...) when you just want unicode_char?
据我了解,TrueType字体格式是在 Unicode 被广泛采用之前开发的,所以如果你想创建一个当时的中文字体,你必须使用当时正在使用的一种编码,而中国大多使用 Big5自 1980 年代中期以来。
因此,必然有一种方法可以使用 Big5 字符编码从 Big5 编码的 TTF 中检索字形。
使用 PIL 渲染字符串的 C 代码以 font_render()
开头函数,最终调用 FT_Get_Char_Index()
找到正确的字形,给定字符代码为 unsigned long
。
但是,PIL 的 font_getchar()
函数,它产生 unsigned long
只接受 Python string
和 unicode
类型,因为它似乎没有对字符进行任何翻译编码本身,似乎获得 Big5 字符集正确值的唯一方法是利用这一事实将 Python unicode
字符强制转换为正确的 unsigned long
值u'\ua7da'
在内部存储为整数 0xa7da
,可以是 16 位还是 32 位,具体取决于您编译 Python 的方式。
TBH,这涉及到相当多的猜测,因为我没有费心去研究 ImageFont.truetype()
的 encoding
参数究竟是什么效果是,但从外观上看,它不应该对字符编码进行任何转换,而是允许单个 TTF 文件支持相同字形的多个字符编码,使用 FT_Select_Charmap()
函数在它们之间切换。
所以,据我了解,FreeType 库与 TTF 文件的交互是这样的......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class TTF(object):
glyphs = {}
encoding_maps = {}
def __init__(self, encoding='unic'):
self.set_encoding(encoding)
def set_encoding(self, encoding):
self.current_encoding = encoding
def get_glyph(self, charcode):
try:
return self.glyphs[self.encoding_maps[self.current_encoding][charcode]]
except KeyError:
return ' '
class MyTTF(TTF):
glyphs = {1: '我',
2: '曎'}
encoding_maps = {'unic': {0x6211: 1, 0x66ce: 2},
'big5': {0xa7da: 1, 0x93be: 2}}
font = MyTTF()
print 'Get via Unicode map: %s' % font.get_glyph(0x6211)
font.set_encoding('big5')
print 'Get via Big5 map: %s' % font.get_glyph(0xa7da)
...但是由每个 TTF 提供 encoding_maps
变量,并且没有要求 TTF 为 Unicode 提供一个。事实上,在采用 Unicode 之前创建的字体不太可能有。
假设所有这些都是正确的,那么 TTF 没有任何问题 - 问题只是 PIL 使得访问没有 Unicode 映射的字体的字形有点尴尬,并且所需字形的 unsigned long
字符代码大于 255。
关于python - 生成字体名称无法正确解码的字符图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16886481/
我正在尝试使用以下 keytool 命令为我的应用程序生成 keystore : keytool -genkey -alias tomcat -keystore tomcat.keystore -ke
编辑:在西里尔正确解决问题后,我注意到只需将生成轴的函数放在用于生成标签的函数下面就可以解决问题。 我几乎读完了 O'Reilly 书中关于 D3.js 的教程,并在倒数第二页上制作了散点图,但是当添
虽然使用 GraphiQL 效果很好,但我的老板要求我实现一个用户界面,用户可以在其中通过 UI 元素(例如复选框、映射关系)检查呈现给他们的元素并获取数据,这样做将为该人生成 graphql 输入,
我尝试在 Netbean 6.8 中使用 ws-import 生成 Java 类。我想重新生成 jax-ws,因为在 ebay.api.paypalapi 包中发现了一个错误(我认为该错误是由于 Pa
我有一个 perl 脚本,它获取系统日期并将该日期写入文件名。 系统日期被分配给 TRH1 变量,然后它被设置为一个文件名。 $TRH1 =`date + %Y%m%d%H%M`; print "TR
我是 Haskell 的新手,需要帮助。我正在尝试构建一种必须具有某种唯一性的新数据类型,因此我决定使用 UUID 作为唯一标识符: data MyType = MyType { uuid ::
我制作了一个脚本,它可以根据 Mysql 数据库中的一些表生成 XML。 该脚本在 PHP 中运行。 public function getRawMaterials($apiKey, $format
所以这是我的项目中的一个问题。 In this task, we will use OpenSSL to generate digital signatures. Please prepare a f
我在 SAS LIFEREG 中有一个加速故障时间模型,我想绘制它。因为 SAS 在绘图方面非常糟糕,我想实际重新生成 R 中曲线的数据并将它们绘制在那里。 SAS 提出了一个尺度(在指数分布固定为
我正在为 Django 后端制作一个样板,并且我需要能够使它到达下一个下载它的人显然无法访问我的 secret key 的地方,或者拥有不同的 key 。我一直在研究一些选项,并在这个过程中进行了实验
我正在创建一个生成采购订单的应用程序。我可以根据用户输入的详细信息创建文本文件。我想生成一个看起来比普通文本文件好得多的 Excel。有没有可以在我的应用程序中使用的开源库? 最佳答案 目前还没有任何
我正在尝试使用 ScalaCheck 为 BST 创建一个 Gen,但是当我调用 .sample 方法时,它给了我 java.lang.NullPointerException。我哪里错了? seal
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我尝试编写一些代码,例如(在verilog中): parameter N = 128; if (encoder_in[0] == 1) begin 23 binary_out = 1;
我正忙于在 Grails 项目中进行从 MySQL 到 Postgres 的相当复杂的数据迁移。 我正在使用 GORM 在 PostGres 中生成模式,然后执行 MySQL -> mysqldump
如何使用纯 XSLT 生成 UUID?基本上是寻找一种使用 XSLT 创建独特序列的方法。该序列可以是任意长度。 我正在使用 XSLT 2.0。 最佳答案 这是一个good example 。基本上,
我尝试安装.app文件,但是当我安装并单击“同步”(在iTunes中)时,我开始在设备上开始安装,然后停止,这是一个问题,我不知道在哪里,但我看到了我无法解决的奇怪的事情: 最佳答案 似乎您没有在Xc
自从我生成 JavaDocs 以来已经有一段时间了,我确信这些选项在过去 10 年左右的时间里已经得到了改进。 我能否得到一些有关生成器的建议,该生成器将输出类似于 .Net 文档结构的 JavaDo
我想学习如何生成 PDF,我不想使用任何第三方工具,我想自己用代码创建它。到目前为止,我所看到的唯一示例是我通过在第 3 方 dll 上打开反射器查看的代码,以查看发生了什么。不幸的是,到目前为止我看
我正在从 Epplus 库生成 excel 条形图。 这是我成功生成的。 我的 table 是这样的 Mumbai Delhi Financial D
我是一名优秀的程序员,十分优秀!