2 Star 22 Fork 12

Walkline / MicroPython New FontLib

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

MicroPython New FontLib

项目介绍

使用MicroPython 开发板读取自定义字库并显示

获取完整项目

因为项目中使用了子模块 FontMaker Clientbinary分支 和 OLED Research,所以要获取完整项目代码需要如下操作

克隆方式

$ git clone --recursive https://gitee.com/walkline/micropython-new-fontlib.git

下载压缩文件方式

或者克隆时未使用--recursive参数的,使用如下代码更新子模块

$ cd micropython-new-fontlib
$ git submodule update --init --recursive

如何使用和测试

生成字库文件

生成字库文件详细说明参考 FontMaker Client 项目文档

直接运行

$ client/youyuan_16.cmd

会生成一个combined.bin文件,字库文件信息如下

参数 数值 说明
字体 幼圆
字号 16 像素
字重 普通 不加粗、不斜体、无下划线
字符宽度 固定
宽度 16 像素
高度 16 像素
水平偏移 0 像素
垂直偏移 0 像素
扫描方式 垂直扫描
字节顺序 低位在前

使用电脑测试

直接运行

$ python fontlib.py

会显示相关信息,包括:

  • 字库信息
  • 获取的字模数据
  • 字模打印预览

完整输出内容如下

HZK Info: .//client/combined.bin
    file size : 261972
  font height : 16
    data size : 32
    scan mode : Vertical
   byte order : LSB
   characters : 7710

!: b'\x00\x00\x00\x00\x00\x00\x08\x00\x0c\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x00\x00\x08\x00\x08\x00\x00\x00'

☆: b'\x00\x00\x00\x00\x00\x80\x01\x80\x01\x80\x01@\x02@~? \x04\x10\x08\x0c\x10\x08\x10\x08\x90\x0bH\x148\x18\x08'

⒉: b'\x00\x00\x00\x00\x00\x00\x07\xc0\x08@\x00@\x00@\x00@\x00\x80\x01\x00\x01\x00\x02\x00\x04\x00\x0c\x08\x0f\xcc\x00\x00'

,: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00p\x000\x00 \x00'

我: b'\x00\x00\x00@\x07PxH\x08D\x08D\x7f\xfe\x08D\x08D\t(\x0e0x0\x080\x08R\t\x8ax\x06'

ㄘ: b'\x00\x00\x00\x00\x00\x00\x01\x00\x01\x80\x00\x80\x01\x00\x03\xf0\x1d\x00\x01\x00\x02\xe0\x03`\x00@\x00\x80\x00\x00\x00\x00'

■: b'\x00\x00\x00\x00\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff'

B: b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x060\x068\x060\x06p\x07\xf0\x06\x18\x06\x18\x06\x18\x07\xf0\x00\x00\x00\x00'

中: b'\x00\x00\x01\x00\x01\x00\x01\x00?\xfc!\x04!\x04!\x04!\x04!\x04!\x04?\xfc\x01\x00\x01\x00\x01\x00\x01\x00'

爱: b'\x00\x00\x00\x00?\xf8\x11\x10\t\x10?\xfcD\x02B\x02\x1f\xf8\x04\x00\x07\xf8\x0e\x08\x13\x10 \xe0\x01\xe0\x1e\x1e'

β: b'\x00\x00\x00\x00\x00\x00\x01\xe0\x01\x10\x030\x02 \x02\xc0\x02`\x06 \x04 \x04`\x04`\x07\xc0\x0c\x00\x08\x00'

あ: b"\x00\x00\x00\x00\x03\x00\x03\x00\x02\xc0\x1f\x80\x02\x00\x06\x80\x07\xf0\x0c\x98\x15\x0c'\x0c&\x0c/\x088\x10\x01\xe0"

H: b'\x00\x00\x00\x00\x00\x00\xe7\x00B\x00B\x00B\x00B\x00~\x00B\x00B\x00B\x00B\x00\xe7\x00\x00\x00\x00\x00'

华: b'\x00\x00\x00\x00\x08@\x08H\x18p(\xc0+BHB\x08~\x01\x00\x01\x00\x7f\xfe\x01\x00\x01\x00\x01\x00\x01\x00'

ǚ: b"\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x08\x004\x00C\x00C\x00C\x00C\x00C\x00C\x00'\x00\x18\x00\x00\x00"

e: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00B\x00~\x00@\x00@\x00B\x00<\x00\x00\x00\x00\x00'

l: b'\x00\x00\x00\x00\x00\x00p\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00|\x00\x00\x00\x00\x00'

o: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00B\x00B\x00B\x00B\x00B\x00<\x00\x00\x00\x00\x00'

⑴: b'\x00\x00\x00\x00\x08\x00\x10\x08!\x84 \x82@\x82@\x83@\x81@\x81@\x81@\x82 \x82 \x84\x13\xc4\x10\x08'

................ ................ ................ ................ ................ ................
................ ................ ................ ................ .........@...... ................
................ ........@....... ................ ................ .....@@@.@.@.... ................ 
....@........... .......@@....... .....@@@@@...... ................ .@@@@....@..@... .......@........
....@@.......... .......@@....... ....@....@...... ................ ....@....@...@.. .......@@.......
....@........... .......@.@...... .........@...... ................ ....@....@...@.. ........@.......
....@........... ......@..@...... .........@...... ................ .@@@@@@@@@@@@@@. .......@........
....@........... .@@@@@@...@@@@@@ .........@...... ................ ....@....@...@.. ......@@@@@@....
....@........... ..@..........@.. ........@....... ................ ....@....@...@.. ...@@@.@........
....@........... ...@........@... .......@........ ................ ....@..@..@.@... .......@........
....@........... ....@@.....@.... .......@........ ................ ....@@@...@@.... ......@.@@@.....
....@........... ....@......@.... ......@......... ................ .@@@@.....@@.... ......@@.@@.....
................ ....@...@..@.... .....@.......... ................ ....@.....@@.... .........@......
....@........... ....@.@@.@..@... ....@@......@... .@@@............ ....@....@.@..@. ........@.......
....@........... ...@.@....@@@... ....@@@@@@..@@.. ..@@............ ....@..@@...@.@. ................
................ ...@@.......@... ................ ..@............. .@@@@........@@. ................

................ ................ ................ ................ ................ ................
................ ................ .......@........ ................ ................ ................
.@@@@@@@@@@@@@@@ ................ .......@........ ..@@@@@@@@@@@... ................ ......@@........
.@@@@@@@@@@@@@@@ ................ .......@........ ...@...@...@.... .......@@@@..... ......@@........
.@@@@@@@@@@@@@@@ .....@@@@@@@.... ..@@@@@@@@@@@@.. ....@..@...@.... .......@...@.... ......@.@@...... 
.@@@@@@@@@@@@@@@ .....@@...@@.... ..@....@.....@.. ..@@@@@@@@@@@@.. ......@@..@@.... ...@@@@@@.......
.@@@@@@@@@@@@@@@ .....@@...@@@... ..@....@.....@.. .@...@........@. ......@...@..... ......@.........
.@@@@@@@@@@@@@@@ .....@@...@@.... ..@....@.....@.. .@....@.......@. ......@.@@...... .....@@.@.......
.@@@@@@@@@@@@@@@ .....@@..@@@.... ..@....@.....@.. ...@@@@@@@@@@... ......@..@@..... .....@@@@@@@....
.@@@@@@@@@@@@@@@ .....@@@@@@@.... ..@....@.....@.. .....@.......... .....@@...@..... ....@@..@..@@...
.@@@@@@@@@@@@@@@ .....@@....@@... ..@....@.....@.. .....@@@@@@@@... .....@....@..... ...@.@.@....@@..
.@@@@@@@@@@@@@@@ .....@@....@@... ..@@@@@@@@@@@@.. ....@@@.....@... .....@...@@..... ..@..@@@....@@..
.@@@@@@@@@@@@@@@ .....@@....@@... .......@........ ...@..@@...@.... .....@...@@..... ..@..@@.....@@..
.@@@@@@@@@@@@@@@ .....@@@@@@@.... .......@........ ..@.....@@@..... .....@@@@@...... ..@.@@@@....@...
.@@@@@@@@@@@@@@@ ................ .......@........ .......@@@@..... ....@@.......... ..@@@......@....
.@@@@@@@@@@@@@@@ ................ .......@........ ...@@@@....@@@@. ....@........... .......@@@@.....

................ ................ ................ ................ ................ ................
................ ................ ................ ................ ................ ................
................ ....@....@...... ................ ................ ................ ................
@@@..@@@........ ....@....@..@... ................ ................ .@@@............ ................
.@....@......... ...@@....@@@.... ...@.@.......... ................ ...@............ ................ 
.@....@......... ..@.@...@@...... ....@........... ................ ...@............ ................
.@....@......... ..@.@.@@.@....@. ..@@.@.......... ................ ...@............ ................
.@....@......... .@..@....@....@. .@....@@........ ..@@@@.......... ...@............ ..@@@@..........
.@@@@@@......... ....@....@@@@@@. .@....@@........ .@....@......... ...@............ .@....@.........
.@....@......... .......@........ .@....@@........ .@@@@@@......... ...@............ .@....@.........
.@....@......... .......@........ .@....@@........ .@.............. ...@............ .@....@.........
.@....@......... .@@@@@@@@@@@@@@. .@....@@........ .@.............. ...@............ .@....@.........
.@....@......... .......@........ .@....@@........ .@....@......... ...@............ .@....@.........
@@@..@@@........ .......@........ ..@..@@@........ ..@@@@.......... .@@@@@.......... ..@@@@..........
................ .......@........ ...@@........... ................ ................ ................
................ .......@........ ................ ................ ................ ................

................
................
....@...........
...@........@...
..@....@@....@..
..@.....@.....@.
.@......@.....@.
.@......@.....@@
.@......@......@
.@......@......@
.@......@......@
.@......@.....@.
..@.....@.....@.
..@.....@....@..
...@..@@@@...@..
...@........@...

使用开发板测试 1

推荐使用 AMPY Batch Tool (ab工具) 进行文件上传和调试操作

# 上传文件
$ ab

# 进入 repl 模式
$ ab --repl

# 运行开发板上的文件
# 使用快捷键 Ctrl-T
>>>
Run onboard file
    [1] /boot.py
    [2] /drivers/ssd1306.py
    [3] /fontlib.py
Choose a file: 3
>>>

# 在开发板上运行本地文件
# 使用快捷键 Ctrl-R
>>> Run local file
    [1] fontlib.py
    [2] drivers\ssd1306.py
Choose a file: 1
>>>

使用开发板测试 2

这是把fontlib.py文件中非MicroPython代码精简掉,并编译为字节码再运行测试的方法

# 上传文件
$ ab abconfig-mpy

因为上传文件中已经包含了main.py,所以直接复位根据提示进行选择,就可以看到效果了

使用图标字体生成字库

方法参见 使用图标字体生成字库

选取其它语种字符的方法

GB2312收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的 682 个全角字符

可以用键盘输入它们,但是并不一定简单,好在我们还可以从 GB2312简体中文编码表 页面中直接查看复制它们

关于速度

以当前字库文件举例:

  • 文件名:combined.bin
  • 文件大小:261,972字节
  • GB2312索引表大小:17,672字节
  • 点阵大小:16x16像素
  • 字符数据大小:32字节
  • 字符总数:7710个(包含ASCIIGB2312
  • 实例化FontLib时打开字库文件,读取文件头信息,大约 12 ms
  • 同时读取?的字符数据作为占位符,大约 5 ms
  • 打印字库信息,大约 39 ms(简直无语,建议实际使用时不要打印)
  • 检索字符数据前再次打开字库文件,大约 12 ms
  • 检索字符数据,每字符大约 12 ms
  • 字符数据使用Dict存储,字符Unicode值作为关键字,取值耗时可以忽略
  • 显示字符耗时未统计

关于提速

决定显示速度的因素有两方面:

  • 从字库中读取指定字符的字模数据
  • 在 oled 中显示

显示部分,MicroPython已经提供了SSD1306驱动,使用FrameBuffer进行数据管理,我相信官方的实力,所以显示部分的速度假设已经没有提升空间了

数据部分,最开始的思路就是“完成功能”,所以在读取的时候是这个流程:

  1. 打开字库文件
  2. 取一个字符
  3. 分段查找字符在索引表中的偏移量
  4. 定位到偏移量读取字模数据
  5. 从第2步开始循环,直到读取所有字符数据

分段的意思是:在Python中打开文件,它不提供查找功能,需要先读取文件内容再进行查找,对于开发板来说,一次性读取全部文件肯定会导致内存溢出,所以需要分段读取一段合理长度的数据再进行查找,在查找到之前就需要不停的分段读取

这个方法的问题在于,每个字符都要从索引表的开始位置进行查找,比较浪费

提速的思路就是,在每次分段读取数据的时候查找所有字符,减少分段次数

继续查找资料,有人说使用read代替seek可以提高定位的效率,在电脑上进行了简单测试,300M 的文件使用readseek快大约0.2 ms,但是这个方法有个致命问题,虽然read读取到的数据并不使用,但也会分配内存空间,在开发板上运行的结果就是,更慢了

对比一下三种方式的读取速度(毫秒)

字库文件信息:

  • 文件大小:500024 字节
  • 字符总数:8932 个
  • 数据大小:54 字节
原方法 新方法(seek) 新方法(read)
打开字库 27.51 26.22 61.21
字符数 原方法 新方法(seek) 新方法(read)
240 13.09 6.50 159.28
227 16.05 8.22 /
767 内存溢出 内存溢出 /

注:统计结果为平均时间

这里的字符数是包含了重复字符的总数,实际获取数据时是要去重的

读取速度还与字符在索引表中的相对位置有关,相对位置靠前的字符当然能更快被找到,反之则更慢

一次性读取太多的数据也会导致内存溢出,所以在实际使用时不建议一次性读取太多

手动调用垃圾回收(gc.collect())的时机一定要掌握好,并不是任何时候手动调用都能起到预期的作用,有时还会起到反作用

对于能够自动回收的,如函数内部的变量,可以省去手动调用的操作

统计运行时间使用的装饰器

from utime import ticks_us, ticks_diff

def cal_time(fn):
    def wrapper(*args,**kwargs):
        starTime = ticks_us()
        f = fn(*args,**kwargs)
        print('%s() runtime: %s ms' % (fn.__name__, ticks_diff(ticks_us(), starTime) / 1000))
        return f
    return wrapper

关于测速

又增加了一个单独测速的文件fontlib_test.py,发现一个现象,虽然知道和缓存有关,但是具体怎么实现的并不了解

这里测速使用了两个方法

  • 一次获取所有字符的字模数据
  • 分段获取所有字符的字模数据

单独测试这两种方法,得到的结果如下

### method: load all
### 240 chars, get 111 chars: 1145.765 ms, avg: 10.32221 ms
### method separated
### 0 get 18 chars: 201.403 ms, avg: 11.18906 ms
...
### 9 get 22 chars: 169.531 ms, avg: 7.705955 ms
### 240 chars, get 197 chars: 1760.472 ms, avg: 9.978033 ms

但是同时测试两种方法的结果却是这样的

### method: load all
### 240 chars, get 111 chars: 1145.765 ms, avg: 10.32221 ms

### method separated
### 0 get 18 chars: 110.468 ms, avg: 6.137111 ms
...
### 9 get 22 chars: 125.306 ms, avg: 5.695727 ms
### 240 chars, get 197 chars: 1170.494 ms, avg: 6.635651 ms

调换顺序的结果也是类似

### method separated
### 0 get 18 chars: 201.403 ms, avg: 11.18906 ms
...
### 9 get 22 chars: 169.531 ms, avg: 7.705955 ms
### 240 chars, get 197 chars: 1760.472 ms, avg: 9.978033 ms

### method: load all
### 240 chars, get 111 chars: 565.726 ms, avg: 5.096631 ms

结论就是,不管是一次性还是分段,只要提前获取了所有字符的字模数据,下次再获取的时候速度就会快很多,不过显然这种提速并没有实际意义

合作交流

  • 联系邮箱:walkline@163.com
  • QQ 交流群:
    • 走线物联:163271910
    • 扇贝物联:31324057

走线物联扇贝物联

MIT License Copyright (c) 2021 Walkline Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

MicroPython 用户自定义中文字库 展开 收起
Python
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Python
1
https://gitee.com/walkline/micropython-new-fontlib.git
git@gitee.com:walkline/micropython-new-fontlib.git
walkline
micropython-new-fontlib
MicroPython New FontLib
master

搜索帮助