1

我从 dafont 存储库中以 TTF 格式收集了许多 10 像素高的位图字体。但是,我无法从它们中提取实际的位图数据,因为它们似乎是矢量形式,并且在渲染时我无法弄清楚点大小和像素大小之间的对应关系。我需要有关软件工具、库或方法的建议,以获取与字母形式对应的准确的每像素位图数据。

一个对问题有意义的示例字体是http://www.dafont.com/commodore-64-pixelized.font

我的目标是使用这些位图字体中的一种或多种来控制基于 Arduino 的视觉持久性 (POV) 显示,作为http://shrimping.it项目的一部分。

POV 设备使用一排 LED 在设备左右移动时通过闪烁 LED 来在空中绘制文本。一个著名的例子是 Adafruit 的 MiniPOV http://www.ladyada.net/make/minipov3/

要编写微控制器代码来闪烁 LED,我需要从字体中获取逐个像素的信息,换句话说,我需要一个方案来从我提供的 TTF 格式文件中提取数据以避免使用为每个字符和每种字体手动执行此操作。

到目前为止,我一直在尝试处理(http://processing.org),但我看不到如何选择点大小来渲染 TTF,以便绘制字体与底层网格完全匹配的像素。一旦我有了这个,我就可以得到信息,但我似乎无法到达那里。Processing 报告的 textAscent 和 textDescent 值似乎是垃圾,至少对于我尝试过的字体。

我正在测试的字体是 Advocut、Andina、Aux DotBitC、BM tube、Commodore 64 Pixelised、Homespun BRK、Nayupixel、SG05 和 Visitor。如果您需要查看原始数据以更好地理解问题,您可以通过在 dafont.com 上搜索来自行检索其中的任何内容。

4

2 回答 2

1

我找到了一个解决方案,它分为三个部分。

阶段1

首先,我使用 Python 从交互式 Python shell 中输出所有可打印的图形 ASCII 字符,方法是输入“python”然后...

import string
print(''.join([chr(x) for x in range(33,127)]))

...它给出了以下字符序列 - 省略 SPACE (32) 和 DEL (127)...

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

第二阶段

然后我启动 Inkscape,使用 View>Grid 激活可见像素网格,并创建一个文本元素,其中包含给定字体的一行中的所有这些字符。我目视检查了哪些字符已退回到非像素字形。(如果没有完全指定一个字符,我认为它会在其中插入一个常规矢量字体,该字体可以是非整数像素数,这会打乱水平字距调整并错误定位剩余字符,因此必须替换它们)。我只用一个问号替换了我看到的所有非像素化字符,这个字符似乎可靠地存在并且在这些字体中具有整数个像素。

一旦所有字符都是干净的像素化字符,选择文本元素(使坐标栏出现在顶部),并放大视图,我就可以将文本定位在 0,0 并选择像素高度手动使像素元素与支持网格对齐(确保当我从 8、9、10、11 像素高切换时,锁定符号被激活以一起缩放水平和垂直尺寸。在某些情况下,这些所谓的当它们正确排列时,10 像素字体实际上是 8 像素或 11 像素高,这解释了一些问题。

有时精确的高度映射会偏离一小部分,所以我通过确保水平像素数正确来调整它(例如,有时实际高度是分数,比如 618 像素宽但 7.005 高。通过沿着字符扫描,你可以看到是否像素稍短或稍长,并将宽度设置为整数,直到像素适合网格。高度的浮点差异在 Inkscape 中几乎不可见,并且对导出没有明显影响(其中分数被四舍五入)但是如果水平计数错误,则会拍摄像素映射,并且在您尝试量化时会因为偏移而产生水平模糊像素。

最后,仍然选择文本元素,我选择了文件>导出位图并选择了“选择”选项卡。导出具有 8、10、11 或在上一步中发现的任何像素数的 PNG,生成具有完美像素映射的像素图形 - 可以在该文件上编写一个简单的例程来提取位图。

第三阶段

最后,必须编写一个程序来导入 PNG 并为 POV 位图提取正确的每个字符信息。

我想出了一个例程,它可以可靠地检测字符的水平范围,并且可以将它们分割成我的 POV 的单独序列。这些不是等宽字体,因此每个字符的宽度是不可预测的——例如感叹号通常只有两个像素宽。需要为包含两个空格的双引号字符编码特殊情况。

我的提取程序的来源现在在...

http://shrimping.it/shrimp/project/pov/font/extract_font.py

...并且可以通过 CDing 到目录并运行来在目录中的一组 png 文件上运行

python extract_font.py

然后为每个字符生成单独的位图,提取到每个字体的单独目录中。

于 2012-10-20T15:53:39.690 回答
0

Python3

I've tried to be descriptive, but you can simplify to work how you need it to.

Requirements: PIL (Pillow)

PIL's ImageDraw and ImageFont module

# pip install Pillow
from PIL import Image, ImageFont, ImageDraw

# use a truetype font (.ttf)
# font file from fonts.google.com (https://fonts.google.com/specimen/Courier+Prime?query=courier)
font_path = "fonts/Courier Prime/"
font_name = "CourierPrime-Regular.ttf"
out_path = font_path

font_size = 16 # px
font_color = "#000000" # HEX Black

# Create Font using PIL
font = ImageFont.truetype(font_path+font_name, font_size)

# Copy Desired Characters from Google Fonts Page and Paste into variable
desired_characters = "ABCČĆDĐEFGHIJKLMNOPQRSŠTUVWXYZŽabcčćdđefghijklmnopqrsštuvwxyzž1234567890‘?’“!”(%)[#]{@}/&\<-+÷×=>®©$€£¥¢:;,.*"

# Loop through the characters needed and save to desired location
for character in desired_characters:
    
    # Get text size of character
    width, height = font.getsize(character)
    
    # Create PNG Image with that size
    img = Image.new("RGBA", (width, height))
    draw = ImageDraw.Draw(img)
    
    # Draw the character
    draw.text((-2, 0), str(character), font=font, fill=font_color)
    
    # Save the character as png
    try:
        img.save(out_path + str(ord(character)) + ".png")
    except:

        print(f"[-] Couldn't Save:\t{character}")
于 2021-04-13T03:33:07.393 回答