You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过代码将.tiff文件转换为Windows废弃字体.fnt文件

从TIFF生成Windows废弃.fnt字体文件的可行方案

由于.fnt是Windows早已废弃的点阵字体格式,目前没有主流开源库(C#/Python/Java)提供直接转换支持,只能通过手动解析格式、拼接二进制数据来实现,核心步骤如下:

1. 先搞懂.fnt的二进制结构

.fnt文件本质是结构化二进制文件,核心由三部分组成:

  • 文件头:存储字体基础属性(版本、字符总数、字符宽高、起始ASCII码等)
  • 字符索引表:记录每个字符的点阵数据在文件中的偏移量和字节长度
  • 点阵数据区:每个字符的像素位图(单色点阵通常用字节的每一位表示一个像素)

注:不同版本的.fnt结构略有差异,建议参考旧版Windows SDK文档中的FONTINFO和FONTCHARINFO结构定义。

2. 从TIFF中提取单个字符的点阵

假设你的TIFF是按固定行列排列的字符 sprite 图(比如每行16个字符,每个字符16×16像素),先拆分出每个字符的单色位图:

Python 字符拆分示例

from PIL import Image

# 加载TIFF并转为单色位图(黑白)
img = Image.open("your_font.tiff").convert("1")
# 单个字符的宽高,根据你的图调整
char_w, char_h = 16, 16
# 计算行列数
cols = img.width // char_w
rows = img.height // char_h

char_bitmaps = []
for row_idx in range(rows):
    for col_idx in range(cols):
        # 裁剪单个字符区域
        x0 = col_idx * char_w
        y0 = row_idx * char_h
        char_img = img.crop((x0, y0, x0+char_w, y0+char_h))
        # 把每行像素转为字节(1表示黑色像素,0表示透明)
        row_bytes = []
        for y in range(char_h):
            byte = 0
            for x in range(char_w):
                # 单色图中0是黑,255是白
                if char_img.getpixel((x, y)) == 0:
                    byte |= 1 << (7 - x)  # 按位存储,从左到右对应字节高位到低位
            row_bytes.append(byte)
        char_bitmaps.append(row_bytes)

3. 手动拼接生成.fnt二进制文件

根据.fnt的结构,把文件头、索引表、点阵数据依次写入二进制文件:

C# 生成.fnt示例

using System.Collections.Generic;
using System.IO;

// 简化版.fnt文件头(需根据实际格式调整字段)
struct FntHeader
{
    public ushort Version;      // 通常为0x0300(旧版16位格式)
    public ushort CharCount;    // 字符总数
    public byte CharHeight;     // 字符高度
    public byte AvgCharWidth;   // 平均字符宽度
    public ushort StartAscii;   // 起始ASCII码(比如32对应空格)
}

void CreateFntFile(string outputPath, List<byte[]> charBitmaps)
{
    using (var fs = new FileStream(outputPath, FileMode.Create))
    using (var writer = new BinaryWriter(fs))
    {
        // 写入文件头
        var header = new FntHeader
        {
            Version = 0x0300,
            CharCount = (ushort)charBitmaps.Count,
            CharHeight = 16,
            AvgCharWidth = 16,
            StartAscii = 32
        };
        writer.Write(header.Version);
        writer.Write(header.CharCount);
        writer.Write(header.CharHeight);
        writer.Write(header.AvgCharWidth);
        writer.Write(header.StartAscii);

        // 写入字符索引表:每个条目是4字节(偏移量+长度)
        int currentOffset = sizeof(FntHeader) + charBitmaps.Count * 4;
        foreach (var bitmap in charBitmaps)
        {
            writer.Write(currentOffset);
            writer.Write(bitmap.Length);
            currentOffset += bitmap.Length;
        }

        // 写入所有字符的点阵数据
        foreach (var bitmap in charBitmaps)
        {
            writer.Write(bitmap);
        }
    }
}

关键注意点

  • 必须严格匹配目标.fnt的版本结构,比如有些旧版是32位头,字段顺序会不同
  • 如果TIFF不是规整的字符 sprite 图,需要先做字符分割、对齐、去噪等预处理
  • 彩色.fnt格式复杂度极高,几乎没有实用场景,建议只处理单色点阵

内容的提问来源于stack exchange,提问作者Arnell Vasquez Corona

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:30:44