少走弯路:单片机使用点阵字体通过像素化的正确获取

要在单片机内自由显示文字,必须准备相应的字库。之前也发文介绍过:

在esp32(esp8266) 提供软字库显示中文的解决方案_esp32中文字库-CSDN博客

包括已经开源的项目:

https://github.com/StarCompute/tftziku

 这种字体获取思路是:把GB2312字符集输出到一块画布上,然后获取画布的像素点,依照像素点的值解析成0或者1。单片机的输出类似如下:

 对于字符的显示基本没有问题,但是如果你仔细看就会察觉到这里面有瑕疵:

“2”显示不完整,3的显示不标准。

造成这一问题的原因是因为字符被输出到画布的时候都会边缘模糊,每个像素都是RGB的,哪怕我们使用的字体颜色是纯黑black也同样有这个问题,所以在实际生成这个字库的时候使用了某个值来判断,例如:

            if dotpix[0] > 90 and dotpix[1] > 90 and dotpix[2] > 90:
                # img.getpixel()
                ss += " 1"
                chars += "1"

            else:
                ss += "  "
                chars += "0"

上面的dotpix是dotpix = img.getpixel((d, i)) 从画布获取的对应像素点,dotpix是个RGB的像素点,这个90是一遍一遍尝试过后相对最优的取值。

这个判断值如果给的太大,字库会存在残缺,反之出现严重的粘连,笔画越密集的地方越容易出问题。

这个问题困扰了好久,尝试过各种方案都无法解决,你们从网上能找到的字符像素化很多都是HZK16这种宋体16号的字库,如果要使用其他楷体,雅黑等等以及不同字号的时候就无解了。

哥有强迫症,隔一段时间就尝试找一下方案,各种调整参数,反正各种折腾下来这个时间跨度有一年以上了,直到今天又看了一下,还是不行,然后深入了一下:

im = Image.new('RGB', (256, 256), (0, 0, 0))

在这个Image对象的new方法中深入了一下,看到了

    im = Image()
    if mode == "P" and isinstance(color, (list, tuple)) and len(color) in [3, 4]:
        # RGB or RGBA value for a P image
        from . import ImagePalette

        im.palette = ImagePalette.ImagePalette()
        color = im.palette.getcolor(color)

这个mode,除了RGB和RGBA外居然还有一个P,虽然不懂这个P到底是干啥的,但是大胆尝试了一下:

im = Image.new('P', (256, 256), (0, 0, 0))

这一改就发现之前的dotpix = img.getpixel((d, i)) 工作不正常,以前是个RGB的像素点,现在居然这个像素点直接返回了0或者1,我靠,一下就猜测可能这次对了。

以前是:


            dotpix = img.getpixel((d, i))
            if dotpix[0] > 90 and dotpix[1] > 90 and dotpix[2] > 90:
                # img.getpixel()
                ss += " 1"
                chars += "1"

            else:
                ss += "  "
                chars += "0"

现在是:


            dotpix = img.getpixel((d, i))
            chars+=str(dotpix)

验证如下:

            
            
 111        
1   1       
1   1       
   1        
  1         
 1          
1           
11111       
            
            

    对比一下像素方式生产的结果:



     1 1 1
   1     1
   1     1
         1
       1

         1
   1 1 1 1

最后重新生成的字库显示如下:

这个就是完全正常的,和PCtoLCD2018的输出是一模一样的 。

两种不同模式生成的字放大很多倍后进行对比:

前面是RGB模式,后面是P模式,简单的看就是一个锯齿的问题,其实并不是这么简单,因为这其实又涉及到两种图的基本构成,所以并不是简单的锯齿化这个问题。

详细代码就不贴出来了,了解了原理怎么都可以写出代码来。

  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值