简体   繁体   English

如何在PIL.ImageFont中使用我自己的位图字体?

[英]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.pngchar_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.

相关问题 wxpython-将PIL.ImageFont转换为wx.Font或wx.Bitmap - wxpython - converting PIL.ImageFont to wx.Font or wx.Bitmap PIL.ImageFont 无法打开名称中有空格的字体 - PIL.ImageFont cannot open font with space in name 通过字体名称而不是文件名和跨平台字体选择 PIL.ImageFont - Choosing a PIL.ImageFont by font name rather than filename, and cross-platform font wx.Font使用面部名称,而PIL.ImageFont使用文件名...有什么办法可以将两者关联? - wx.Font uses a facename & PIL.ImageFont uses a filename… Is there any way to relate the two? 如何使用python PIL ImageFont.truetype()? - How to use python PIL ImageFont.truetype()? 如何使用 PIL 的 ImageFont 类获取字体像素高度? - How to get the font pixel height using PIL's ImageFont class? 为什么在打开带有“PIL.ImageFont”的 TTF 时会收到“`OSError: unknown file format`”? - Why am I getting "`OSError: unknown file format`" when opening a TTF with `PIL.ImageFont`? 如何在不指定绝对路径的情况下使用 PIL.ImageFont.truetype 加载字体文件? - How I can load a font file with PIL.ImageFont.truetype without specifying the absolute path? 如何在 PIL.ImageFont.truetype() 中指定字体样式路径,同时在 google colab 中编码? - How to specify font style path in PIL.ImageFont.truetype(), while coding in google colab? 为什么来自PIL的ImageFont无法在Python中加载印尼字体? - Why ImageFont from PIL can't load Indonesia font in Python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM