CharacterMatrix 生成带索引的字体库文件解析
按照官方的说明是:字库格式为 C+O+D,C和O两个域为可选域。其中C为32 Bits[4 Bytes]的数据,表示该字库文件中包含的字模总数;O占用的字节数为C*10,即每个字符各占80 Bits,前16 Bits[2 Bytes]为该字模的编码值[MBCS或UNICODE码值,可设置],第二个16 Bits[2 Bytes]为该字模的宽度,第三个16 Bits[2 Bytes]为字模的高度,最后32 Bits[4 Bytes]表示该字模的点阵数据在字库文件中的偏移量[偏移量从D起始处开始计算,即第一个字模的偏移量值为0];D用来描述字库中各字模的点阵数据,占用的字节数与字模大小及生成字库时使用的设置相关;C和O两个域的字节顺序为BigEndian,即高字节在前;
对于图形字模以及使用MBCS编码时添加的UNICODE专有字符,将使用0x0A00~0x0E7F区间作为字模的编码值使用 [覆盖UNICODE编码的果鲁穆奇语、古吉拉特语、奥里雅语、泰米尔语、泰卢固语、卡纳达语、马拉雅拉姆语区间];
下面开始用python进行解析:
def parse_font_library(file_path): with open(file_path, 'rb') as f: # 读取 C 域,获取字模总数 font_count = int.from_bytes(f.read(4), byteorder='big') print(f"字库中包含的字模总数: {font_count}") font_info = {} # 读取 O 域,获取每个字模的信息 for _ in range(font_count): # 读取编码值,占 2 字节 code = int.from_bytes(f.read(2), byteorder='big') # 读取宽度,占 2 字节 width = int.from_bytes(f.read(2), byteorder='big') # 读取高度,占 2 字节 height = int.from_bytes(f.read(2), byteorder='big') # 读取偏移量,占 4 字节 offset = int.from_bytes(f.read(4), byteorder='big') font_info[code] = { 'width': width, 'height': height, 'offset': offset } # 记录 D 域起始位置 d_start = f.tell() # 读取 D 域,即字模点阵数据 font_data = f.read() return font_info, font_data, d_start def get_font_matrix(font_info, font_data, d_start, ascii_code): if ascii_code not in font_info: print(f"未找到编码为 {ascii_code} 对应的字模。") return None info = font_info[ascii_code] width = info['width'] height = info['height'] offset = info['offset'] + d_start # 计算字模数据长度 data_length = (width * height + 7) // 8 # 提取对应字模数据 matrix_data = font_data[offset - d_start:offset - d_start + data_length] matrix = [] for byte in matrix_data: binary_str = bin(byte)[2:].zfill(8) matrix.extend([int(bit) for bit in binary_str]) result_matrix = [matrix[i * width:(i + 1) * width] for i in range(height)] return result_matrix def print_font_matrix(matrix): if matrix is None: return for row in matrix: for bit in row: if bit == 1: print('*', end=' ') else: print(' ', end=' ') print() if __name__ == "__main__": file_path = "your_font_file.bin" font_info, font_data, d_start = parse_font_library(file_path) while True: try: ascii_input = input("请输入字符的编码(十六进制,如 0x41;输入 'q' 退出):") if ascii_input.lower() == 'q': break if ascii_input.startswith('0x'): ascii_code = int(ascii_input, 16) else: print("输入格式有误,请输入十六进制编码,如 0x41。") continue matrix = get_font_matrix(font_info, font_data, d_start, ascii_code) print_font_matrix(matrix) except ValueError: print("输入无效,请输入有效的十六进制编码。")
代码解释
parse_font_library 函数
读取 C 域:从文件开头读取 4 个字节,以大端字节序转换为整数,得到字库中包含的字模总数,并打印该信息。
读取 O 域:循环 font_count 次,每次读取 10 个字节,分别获取字模的编码值、宽度、高度和偏移量,并将这些信息存储在 font_info 字典中。
记录 D 域起始位置:使用 f.tell() 记录 D 域的起始位置,方便后续计算偏移量。
读取 D 域:读取文件剩余部分,即字模的点阵数据。
get_font_matrix 函数
检查编码是否存在:检查输入的编码是否在 font_info 字典中,如果不存在则提示未找到对应字模。
计算偏移量:将存储的偏移量加上 D 域的起始位置,得到字模点阵数据在文件中的实际偏移量。
提取字模数据:根据宽度和高度计算字模数据的长度,并从 font_data 中提取对应的数据。
转换为矩阵:将提取的字节数据转换为二进制矩阵。
print_font_matrix 函数
遍历矩阵,将值为 1 的位置打印为 *,值为 0 的位置打印为空格。
主程序
加载字库:调用 parse_font_library 函数加载字库文件,并获取字模信息、点阵数据和 D 域起始位置。
循环输入:提示用户输入字符的十六进制编码,输入 q 退出。
获取并打印字模矩阵:根据用户输入的编码调用 get_font_matrix 函数获取字模矩阵,并调用 print_font_matrix 函数打印矩阵。
使用说明
将 "your_font_file.bin" 替换为实际的字库文件路径。
运行代码后,程序会显示字库中包含的字模总数。
按照提示输入字符的十六进制编码(如 0x41),程序会打印对应的字模矩阵。输入 q 可退出程序。