0xAA55 发表于 2019-4-1 20:24:24

【VB6】用于单片机显示GB2312中文字符的字模生成器

单片机显示中文一直以来都是一个比较令人头疼的问题——也是一个比较令某些欧美程序员无法理解的问题。我曾经被人说“你也就用不了几个字符,甚至26个英文字母你都用不全,你干嘛要纠结字符的加载和缓存的问题呢?”以及“我告诉你,不要用输入法,你别指望输入法能拯救你那少得可怜的词汇量。我认为使用输入法的程序员都是外行。”……等各种令我们这些母语不是ASCII的人感到困惑的言论。

单片机的ROM一般不会多到能让你随便存下几张照片的,就别说GB2312那么多汉字了。在Unicode从0x20到0xFFFF之间,我们的GB2312编码的字符个数大概是7541个。这些汉字基本足够使用了,但依然有很多生僻字是无法显示的。为了解决这些生僻字,就有了GBK,但单片机的话还是不讲究了。

通常情况下我们解决字体显示用的是FreeType库,用它来解析ttf格式的字体文件然后动态绘制、缓存。但这个库用在单片机上是不现实的。所以单片机的字体绘制基本靠的是位图打点绘制的过程。

说白了就是每个字符生成一个位图,然后把位图拿去绘图,就是单片机的常用做法了。



图中的文件名是按照Unicode字符编号命名的,而不是GB2312编码。

这些字模是我自己写的一个字模生成器生成的。你可以选择字体和大小,以及生成的BMP的格式。实际用在单片机上的时候,你是要去掉这些bmp文件的文件头的,因为都是些重复的信息(除了每个字的宽高以外)。
生成字模的原理用的是TextOut()这个API来绘制文字,然后把绘制的文字存储为文件。

而字体的选择用的是CreateFont()这个API。将其选入HDC句柄后就可以让TextOut()的行为按照指定字体来绘制。


(字体预览用的文章出处:微信公众号 利维坦《放心,有性感缺失的不是你一个》转侵删)

对于较小的字体,它只有黑白两色,用1bit存储一个像素的方式是最合适不过的了。对于单片机也是最合适的。不过,对于平均12x12像素的文字,7541个字符,需要7541x12x12/8 = 7541 x 18 = 135738 Bytes ≈ 133 KiB,而这个大小其实已经超出了Blue Pill上面带的单片机STM32F103C8T6的ROM容量128 KiB。目测如果真要投入应用,它应该是存储了一部分在SD卡以及类似的存储器里然后由单片机读取使用的。

对于存储容量稍大一点的单片机,或者其它物联网机器比如树莓派、香蕉派,带一个自己编程外设控制的屏幕,则可以选用较大的、带抗锯齿的字体。对于这样的字体,我生成的位图是8-bit调色板格式、256色,调色板起到一个预览的时候提示灰度值的作用。实际存储的是一字节一像素的灰度值,0表示“无”或者“白底”,255表示“有”或者“黑字”。





字模生成器src:
bin:
下载的时候请留意校验信息:
名称: gbkbmp.exe
大小: 61440 字节 (60 KiB)
CRC32: C128C363
CRC64: 4001AA0613392877
SHA256: 70AE0C793ABC646091B38A64793B3823D15DC23C0F5186A603A3B70BF603250D
SHA1: 832FFF75D005358AC7A9281CFF2656D44CD6B6F2
BLAKE2sp: 9C70A90FF99E36EB0E73893C7C2DA637E81CDDA407C8B00941AA7CAC2810AC00

另外这软件在我的机器上生成一套字模只需要1、2秒。请大家帮忙测试它的效率。

Ayala 发表于 2019-4-2 14:04:22

本帖最后由 Ayala 于 2019-4-2 14:07 编辑

一个12号字用18bytes太奢侈了 应该选择一种合适的树压缩它

0xAA55 发表于 2019-4-2 21:40:52

Ayala 发表于 2019-4-2 14:04
一个12号字用18bytes太奢侈了 应该选择一种合适的树压缩它

确实…在考虑用zlib压缩

jinlong0186 发表于 2024-9-12 22:22:52

啥也不说了,感谢楼主分享哇!
页: [1]
查看完整版本: 【VB6】用于单片机显示GB2312中文字符的字模生成器