[英]How to use my own bitmap font in PIL.ImageFont?
I created a bitmap font, basically a 256x256 png image where each character occupies 8x8 tile. 我创建了一个位图字体,基本上是一个256x256 png图像,其中每个字符占用8x8瓦片。 I want to use it with Pillow as ImageFont but there's no info on this in Pillow docs. 我想将其与Pillow一起用作ImageFont,但Pillow文档中对此没有任何信息。 It says I can load bitmap fonts like this 它说我可以像这样加载位图字体
font = ImageFont.load("arial.pil")
but "PIL uses its own font file format to store bitmap fonts." 但是“ PIL使用其自己的字体文件格式来存储位图字体。” so I guess png file won't work. 所以我想png文件将无法工作。 How can I tell PIL to use said bitmap and where each character is on it? 如何告诉PIL使用上述位图以及每个字符在何处?
Not a complete answer, but too much for a comment, and it may be useful or spur someone else to work out the other 60% :-) 这不是一个完整的答案,但太多的评论,可能会有用或促使其他人解决另外60%的问题:-)
I may delete it if anyone else comes up with something better... 如果有人提出更好的建议,我可能会删除它。
You can go to the Pillow repository on Github and download a ZIP file of the code. 您可以转到Github上的Pillow存储库,并下载代码的ZIP文件。
If you go in there and nose around you will find two things that appear to work hand-in-hand, namely a .PIL
file and a .PBM
file. 如果您到那儿走走,您会发现两件事似乎是相互配合的,即.PIL
文件和.PBM
文件。
In Tests/fonts
there is a file called 10x20.pbm
which is actually a PNG
file if you look inside it. 在“ Tests/fonts
有一个名为10x20.pbm
文件,如果您在其中查看的话,它实际上是一个PNG
文件。 So, if you change its name to 10x20.png
you can view it and it looks like this: 因此,如果将其名称更改为10x20.png
,则可以查看它,它看起来像这样:
By the way, if you want to split that into 10x20 size chunks with one letter in each, you can use ImageMagick in Terminal like this: 顺便说一句,如果您想将其分成10x20大小的块,每个块一个字母,则可以在Terminal中使用ImageMagick ,如下所示:
convert 10x20.pbm -crop 10x20 char_%d.png
and you will get a bunch of files called char_0.png
, char_1.png
etc. The first 4 look like this: 您将得到一堆名为char_0.png
, char_1.png
等的文件。前4个如下所示:
If you look in src/PIL/FontFile.py
there is this code that seems to know how to access/generate the metrics for a font: 如果您在src/PIL/FontFile.py
,则此代码似乎知道如何访问/生成字体的度量标准:
#
# The Python Imaging Library
# $Id$
#
# base class for raster font file parsers
#
# history:
# 1997-06-05 fl created
# 1997-08-19 fl restrict image width
#
# Copyright (c) 1997-1998 by Secret Labs AB
# Copyright (c) 1997-1998 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#
from __future__ import print_function
import os
from . import Image, _binary
WIDTH = 800
def puti16(fp, values):
# write network order (big-endian) 16-bit sequence
for v in values:
if v < 0:
v += 65536
fp.write(_binary.o16be(v))
##
# Base class for raster font file handlers.
class FontFile(object):
bitmap = None
def __init__(self):
self.info = {}
self.glyph = [None] * 256
def __getitem__(self, ix):
return self.glyph[ix]
def compile(self):
"Create metrics and bitmap"
if self.bitmap:
return
# create bitmap large enough to hold all data
h = w = maxwidth = 0
lines = 1
for glyph in self:
if glyph:
d, dst, src, im = glyph
h = max(h, src[3] - src[1])
w = w + (src[2] - src[0])
if w > WIDTH:
lines += 1
w = (src[2] - src[0])
maxwidth = max(maxwidth, w)
xsize = maxwidth
ysize = lines * h
if xsize == 0 and ysize == 0:
return ""
self.ysize = h
# paste glyphs into bitmap
self.bitmap = Image.new("1", (xsize, ysize))
self.metrics = [None] * 256
x = y = 0
for i in range(256):
glyph = self[i]
if glyph:
d, dst, src, im = glyph
xx = src[2] - src[0]
# yy = src[3] - src[1]
x0, y0 = x, y
x = x + xx
if x > WIDTH:
x, y = 0, y + h
x0, y0 = x, y
x = xx
s = src[0] + x0, src[1] + y0, src[2] + x0, src[3] + y0
self.bitmap.paste(im.crop(src), s)
self.metrics[i] = d, dst, s
def save(self, filename):
"Save font"
self.compile()
# font data
self.bitmap.save(os.path.splitext(filename)[0] + ".pbm", "PNG")
# font metrics
with open(os.path.splitext(filename)[0] + ".pil", "wb") as fp:
fp.write(b"PILfont\n")
fp.write((";;;;;;%d;\n" % self.ysize).encode('ascii')) # HACK!!!
fp.write(b"DATA\n")
for id in range(256):
m = self.metrics[id]
if not m:
puti16(fp, [0] * 10)
else:
puti16(fp, m[0] + m[1] + m[2])
So hopefully someone has time/knowledge of how to put those two together to enable you to generate the metrics file for your PNG. 因此,希望有人有时间/知道如何将两者结合在一起,使您能够为PNG生成指标文件。 I think you just need something that does the last 10 lines of that code for your PNG. 我认为您只需要为PNG执行该代码的最后10行的代码即可。
There appear to be 23 bytes of header which you can simply replicate, and then there are 256 "entries" , ie 1 for each of 256 glyphs. 头似乎有23个字节,您可以简单地复制它们,然后有256个“条目” ,即256个字形中的每个1个。 Each entry has 10 numbers in it, and each number is 16-bit big endian. 每个条目中都有10个数字,每个数字都是16位大字节序。
Let's look at the header: 让我们看一下标题:
dd if=10x20.pil bs=23 count=1| xxd -c23 | more
00000000: 5049 4c66 6f6e 740a 3b3b 3b3b 3b3b 3230 3b0a 4441 5441 0a PILfont.;;;;;;20;.DATA.
Then you can see the entries using the command below to skip the header and group nicely: 然后,您可以使用以下命令查看条目,以很好地跳过标题和分组:
dd if=10x20.pil bs=23 iseek=1| xxd -g2 -c20
which gives: 这使:
Column 1 appears to be the width of the glyph. 第1列似乎是字形的宽度。
Column 7 is the x-offset of the left edge of the glyph in the image and column 9 is the x-offset of the right edge of the glyph in the image. 列7是图像中字形左边缘的x偏移,列9是图像中字形右边缘的x偏移。 So you will see that column 7 on each line is the same as column 9 on the previous line, ie that the glyphs abutt each other going across the image. 因此,您将看到每行的第7列与前一行的第9列相同,即字形在图像上彼此邻接。
If you look at this extract from further down the file, you can see it starts a new row of glyphs in the output image in the middle of the extract (marked in red). 如果从文件的更下方查看此摘录,则可以看到它在摘录中间(红色标记)在输出图像中开始了新的字形行。 That tells us that the bitmap should be no more than 800 pixels wide and that column 8 is the y-offset of the top of the glyph in the bitmap file and column 10 is the y-offset of the bottom of the glyph in the bitmap. 这说明位图的宽度不应超过800像素,第8列是位图文件中字形顶部的y偏移,第10列是位图中字形底部的y偏移。 。 You should see that when a new line row of glyphs starts in the bitmap file that x goes to zero and column 8 takes the previous value from column 10. 您应该看到,当位图文件中一行新的字形行开始时,x变为零,第8列采用第10列中的前一个值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.