玩转LVGL之:详解LVGL字库格式及显示原理(附字库转换工具)
前言
最近项目上使用到了LVGL做UI,并且需要实现完整中文显示。
LVGL字库常见的使用方式有:
- 使用官方工具制作bin格式字库
- 优点:完全由LVGL接管,开发省心
- 缺点:需要对接文件系统,且经过一层文件系统,效率就变差了,单片机使用时无疑会降低效率
- 使用内置字体
- 优点:字库直接内置在程序数组中,效率最快最高
- 缺点:如果字库很大,MCU内放不下,且每次烧录程序连带着字库数据也烧录一遍
- 使用开源作者LvglFontTool工具制作存储在FLASH中的bin数据
- 优点:直接将字库bin数据存在外部SPI类型的FLASH中,不用每次下载程序时把字库也得烧录一遍
- 缺点:该工具貌似不是很完善,发现比LVGL官方生成的bitmap位图数据大了很多,且部分字体对其有问题。实测生成
优设标题黑字库的16号中文一级+二级+ASCII字符,LVGL官方的bin文件仅为523KB,而LvglFontTool为905KB,大了太多了。并且该工具0.4版本不支持LVGL9,而0.5支持LVGL9,但是根据作者发布信息来看是测试版,实际项目上不敢用。。。
没办法了,都不适合自己的需求,那就?自己制作一个!。。。
软件特性:
- 支持LVGL8、LVGL9
- 支持8、4、2、1抗锯齿
- 支持内置数据和外部bin格式字库
- 实时预览观察抗锯齿效果
软件下载:
软件使用:
- 内部字体:生成
.c文件,直接加入自己的工程编译即可 - 外部字体:生成
.c和.bin文件,.c文件直接加入工程编译,.bin文件烧录至外部FLASH,并对接user_font_get_data函数即可
显示原理与缺陷
在嵌入式图形界面开发中,字符渲染是基础且关键的环节,其实现方式取决于屏幕硬件的显存格式。
- TFT彩色屏:通常采用 RGB565 格式,即每个像素由 16 位(2 字节) 数据定义颜色。
- 单色点阵屏(如常见的 0.96 寸 OLED 或液晶点阵屏):采用 1 位(1 bit) 映射一个像素的二值模式(亮/灭)。因此,1 个字节即可横向描述 8 个像素的状态。
注:部分液晶点阵屏支持灰度显示,其数据格式需另行讨论
在基于单片机的嵌入式显示系统中,渲染 16 像素高度的中西文字符通常采用预生成点阵字库的方案。
具体流程为:利用字符点阵提取工具,将目标字符转换为二进制位图数据。其中:
- 中文汉字:映射为 16×16 的像素矩阵;
- 英文字符:映射为 8×16 的像素矩阵。
系统运行时,单片机直接读取这些预定义数据,依据每一位(Bit)的逻辑状态(0 或 1)控制对应像素点的亮灭,从而在屏幕上重构出清晰的字符图像。
然而,该方案存在显著的局限性:
- 存储效率低: 固定尺寸的矩阵(如 16×16)往往大于字符的实际有效字形区域。字符四周通常包含大量无效的空白像素,导致生成的点阵数据中混入了大量冗余信息,造成了宝贵的 Flash/RAM 空间浪费
- 缺乏标准化: 由于依赖人工或特定工具预先生成,不同来源的字库在取模方式(行列序、极性)、字间距及基线对齐上往往不一致,难以形成一套通用、标准化的字体渲染架构,增加了移植和维护成本
- 字体不美观: 由于生成的是字符点阵,非黑即白,字体边缘没有颜色过渡,所以显示出来的字符有锯齿状
字体渲染与对齐
FreeType是一个开源的字体引擎,主要用于渲染各种字体,包括 TrueType 和 OpenType 格式。它具有以下主要特点:
- 多格式支持:兼容几乎所有主流字体格式,如 TrueType (.ttf)、OpenType (.otf) 等。
- 跨平台:可以在 Windows、Linux、macOS 等多个操作系统上运行。
- 高效渲染:提供高质量的文本渲染效果,包括抗锯齿功能。
LVGL中的字体bitmap数据,就是通过freetype生成的位图掩码数据,也可以说是灰度数据。
LVGL作为一个当下非常流行的嵌入式UI框架,很多功能都是遵循标准化的,字体也不例外,同样是支持freetype直接渲染显示ttf格式字库。
不过在嵌入式单片机中由于资源和性能的问题,大多时候不会渲染ttf格式字库,而是选择使用官方工具生成bin格式的字库,或者内置数组的形式。
现在了解一下freetype是如何渲染显示一个字符的。
先简单了解一下字体相关的一些基本概念:
- baseline:基线,一条虚拟的线,在渲染显示字符时,所有字体统一根据基线的位置上下偏移进行绘制,以保证字体的对其显示及美观性
- ascender:上升部,正值,决定了所有字体的最大高度
- descender:下沉部,负值,从基线到字体底端的高度
- line_height:字体的最大高度,计算方法:line_height = ascender + | descender |
注:大多数情况是 line_height = ascender + | descender | ,但是也有例外,比如Adobe字体的g字母,实际高度要大于ascender + | descender |
先展示一张图,下图参数为:
- 字体名称:优设标题黑.ttf
- 字体大小:16px
- 上升高度(ascender):16
- 下沉高度(descender):5
- 最大高度(line_height):16+5=21

基线(Baseline) 是字体渲染中一条不可见的虚拟参考轴。为了美观性考虑,字符绘制需以基线为基准,结合字体的垂直度量(Ascent/Descent)进行动态偏移。
若忽略中英文及特殊符号在字形边界框(Bounding Box)上的差异,强行统一绘制坐标,将导致文本行出现严重的视觉错位:
-
下伸部(Descender)处理 :如英文小写字母 g,其笔画主体位于基线之下。若强制将其底部对齐基线,字符将悬浮于空中,破坏阅读连贯性。
-
上标与字距(Superscript & Kerning) :如摄氏度符号 °,其标准排版应为上标形式(位于基线上方且字号缩小),并需紧贴前驱字符(如 C)。若按常规字符位置绘制,不仅垂直位置错误,还会产生不自然的巨大间距,严重影响美观度。
所以,当字体大小设置为16像素时,实际占用的矩形区域是21X16。
LVGL渲染显示字体时,固定了基线(base_line)和最大高度(line_height)这两个参数,在16X21这个矩形框内,通过lv_font_fmt_txt_glyph_dsc_t这个结构中的box_w和box_h确定字符的实际显示区域,通过ofs_x和ofs_y定位实际显示的位置,然后取glyph_bitmap中的数据进行渲染,完成一个字符的显示。
抗锯齿参数(BPP)
抗锯齿(Anti-Aliasing)原理
抗锯齿是一种通过亚像素渲染优化字体边缘的技术。其核心在于利用多级灰度值填充字符轮廓边缘的像素,使原本锐利的锯齿状边界在视觉上呈现平滑的渐变过渡,从而显著提升文字的清晰度与美观度。
色彩深度(BPP, Bits Per Pixel)
BPP指图像中每个像素所占用的比特数,直接决定了图像的色彩深度(或灰度等级)。
- 公式:可表示的颜色/灰度数量 = 2bpp
- 关系:BPP越高,色彩层次越丰富,但占用的存储空间也越大
传统点阵显示(1bpp)
常规取模工具生成的字库通常为二值图像(Binary Image)。
像素仅用 0(透明/背景)或 1(前景色)表示。这种非黑即白的模式缺乏中间过渡色,相当于无抗锯齿处理,边缘锯齿感明显。
LVGL多级灰度方案
为平衡显示效果与内存占用,LVGL支持多种BPP格式,将0-255的灰度区间进行不同精度的量化:
| BPP | 存储效率 | 灰度等级 (2bpp) | 描述 |
|---|---|---|---|
| 8bpp | 1字节 = 1像素 | 256级 (0-255) | 最高精度。完整保留256级灰度,抗锯齿效果最平滑,接近矢量字体质感。 |
| 4bpp | 1字节 = 2像素 | 16级 | 中等精度。将灰度量化为16个阶梯,在视觉效果与空间占用间取得良好平衡。 |
| 2bpp | 1字节 = 4像素 | 4级 | 低精度。仅保留4个灰度阶跃,适用于资源极度受限但需轻微柔化边缘的场景。 |
| 1bpp | 1字节 = 8像素 | 2级 (0或1) | 无抗锯齿。即传统的二值点阵,非黑即白,空间占用最小,但边缘锯齿明显。 |
下面一图展示不同bpp下的16号字符A的显示效果,可以明显看出边缘的平滑过渡区别:

实际运行效果(模拟器)
| LVGL8 | LVGL9 |
|---|---|
![]() | ![]() |
ends…




&spm=1001.2101.3001.5002&articleId=159648013&d=1&t=3&u=ea9cf3c08e144bfbb3a5c47cdf60119d)
268

被折叠的 条评论
为什么被折叠?



