【问题标题】:How to extract Bitmap data from TTF bitmap typeface for a POV display?如何从 TTF 位图字体中提取位图数据以进行 POV 显示?
【发布时间】:2012-10-10 22:24:34
【问题描述】:

我从 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 上搜索来自行检索这些数据。

【问题讨论】:

    标签: fonts bitmap processing pixels truetype


    【解决方案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中几乎看不到,对导出没有明显影响(其中分数是四舍五入的) off) 但如果水平计数错误,则拍摄像素映射,并且在尝试量化时会因为偏移而产生水平模糊像素。

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

    第三阶段

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

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

    我的提取例程的源现在在...

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

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

    python extract_font.py
    

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

    【讨论】:

    • 感谢 twitter.com/mgdm/status/259669824769245184twitter.com/gordonjcp/status/259664637342142464 通过 Twitter 提出的建议。还没有通过 Stackoverflow :(
    • Andina 字体在其当前形式中似乎无法使用此解决方法,因为字母之间的间距会变化并且通常不是整数像素(例如 ? 和 N 字符具有部分像素间距)。
    • Nayupixel 字体在间距方面也有类似的问题,但并没有那么糟糕,只需通过独立于垂直拉伸水平,然后使用 Gimp 的 Image>Mode>Indexed> 展平为位图即可恢复1 位颜色。
    • 可以在shrimping.it/shrimp/project/pov/font/png下载成功映射到位图png的字体的结果图像
    【解决方案2】:

    Python3

    我尝试过描述性,但您可以根据需要简化工作。

    要求:PIL(枕头)

    PILImageDrawImageFont 模块

    # 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}")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多