LCD作为终端显示字符串的过程

  • 1.本文目的

  • 2.资源评估

  • 3.显示原理

  • 4.嵌入式上汉字处理

  • 5.结果验证与展示

  • 6.总结

1.本文目的

做嵌入式图形开发,我们往往都会利用到各种GUI进行交互设计,但是对于GUI的字符串处理与中文字库显示,也许并不会特别关注,因为GUI已经帮助我们封装了一些通用的API,在调用相对应的API就可以显示想要的图像和字符串了。那么这些底层原理到底是什么呢?

正好和朋友讨论,我们做嵌入式开发都是将输出信息定位到串口,那能不能定位到I2C、SPI、网络等各种协议上去呢?这个确实是有意思的事情,那正好手上有个树莓派,可以通过DSI或者HDMI来显示,那就把rt-thread的console重定位到LCD上去吧,让树莓派的屏幕代替我们的串口调试助手控制台,这样就不用接上串口看输出信息了。

有了这个想法,于是立即付诸行动。需求很明确,开发平台也已经确定,树莓派4+HDMI屏(分辨率1280x800)。或者接DSI的MIPI屏,我发现树莓派的HDMI驱动原来和DSI的MIPI屏的驱动一样,所以两者没有区别。为了简化验证的操作流程,可以选择rtos,这里我就用比较熟悉的rt-thread。因为rt-thread有着和Linux类似的控制终端,这样更加方便对接。

2.资源评估

有了想法,若要想进行下去,必须评估一下手上的资源是否齐全。下面列出必要的资源

1.树莓派4

选择树莓派4作为验证平台,是我因为现在手上环境搭建已经很方便了。嵌入式开发的痛点和难点就是在环境搭建上,一个好的的开发环境可以达到事半功倍的效果。环境搭建值得好好整理,对于验证各种功能,实现各种特性的验证都十分的好用。

2.hdmi屏

由于已经完成树莓派4的hdmi屏驱动的研究工作,并且hdmi驱动和最后抽象出来的就是FrameBuffer。操作起来不用管底层的实现,只需要向这个Framebuffer的地址处写数据,会自动将这个数据显示到LCD的屏上,十分的方便。并不用关心x,y坐标,像素等等。

3.字库

这里先通过英文字库进行演示,后面再谈中文字库。目前抽取的是开源的GUI中的font_dejavu_40字库进行研究。后面的40表示每个字符高度为40个像素,因为屏的分辨率为1280x800。如果每个字符的高度太小则看起来文字非常的小,在大屏上看起来十分不友好,所以这里选择40个高度的字体,而宽度不定是因为字符的宽度是不是确定的,每个字符有着自己的宽度比如Ll两个数字的宽度就不一样。

有了上述资源,就可以进行后面的探究了,下面来梳理一下显示原理。

3.显示原理

计算机图形本质上就是像素点的集合,更加具体的就是红黄蓝三原色的组合。

三原色的排布组成了一个像素点。实际LCD放大后像素点看起来如下图所示。

而这些像素的亮度决定了最后显示在屏幕上的效果。像素深度(bits per pixel,简称bpp) 描述了每个像素的位数,比如32位则是RGBA8888,24位常见的RGB565和16位常见的565等等。这些都是一个像素所能够表示的信息。

而多个像素可以表示一个图像信息。像素是图像操作的最小单位,所以下面暂时不要考虑颜色信息。

来看一个字库中一个字符的信息

0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x1f, 0x80,  //..+%@@@@@.....0xff, 0x80,  //@@@@@@@@@.....0xff, 0x80,  //@@@@@@@@@.....0xe3, 0x80,  //@%%+..@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x03, 0x80,  //......@@@.....0x7f, 0xfc,  //.@@@@@@@@@@@@@0x7f, 0xfc,  //.@@@@@@@@@@@@@0x7f, 0xfc,  //.@@@@@@@@@@@@@0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............0x00, 0x00,  //..............

上述就是字符1在字符中的存放信息,每个字节按位展开,.表示0,@表示1。则右边的注释展示了该串字符的信息。如果我们将上述信息告诉给cpu,然后CPU处理这些信息放到LCD上显示则可以显示字符串1。

如果把上面的数组用程序解析交给LCD该如何设计。

1.拷贝上述数组到程序里,作为只有一个字符的字库数组array

2.申请一块和framebuff一样大的内存palette,作为图像输入的画板

3.读取array第一和第二个元素,将第一个元素按高位解析,如果是0向palette填充黑色像素点,1向palette填充白色像素点。

字库中的每一位对应LCD的一个像素,如果对于RGB565来说,则表示2个字节。那我们可以做这样的理解。字库中1的宽度是32个像素,高度是40个像素。

于是可以做标准字库的解析了。一个标准字库是包含多个这样的字符串结构的,所以字符串需要一张表记录这些信息,根据asiic码表排序,字库的存放顺序也可如此,然后一个索引表记录着每个字符串的宽度,数组所在的起始地址信息,有了这些信息,就可以依次做解析然后转换成像素进行显示了。

4.嵌入式上汉字处理

嵌入式上受到资源限制,汉字字库一直都不好解决,不能为了显示汉字把2500~7000个汉字都收录进去,这样需要的内存资源和flash资源十分庞大。为了解决这个问题,一般都是自定义字库,就是首先列出该项目中实际会用到的所有汉字,然后利用特定的软件生成对应的像素字符数组,生成的同时,也会对应这一张map表,方便查找具体汉字的位置。

在处理英文的时候,由于所需的字符很少,可以通过ASCII码进行索引,汉字则可以自定义索引规则,这些都是需要自己设计处理的。但是原理是一样的。

5.结果验证与展示

经过上述的操作,已经完成了lcd console的任务,可以给自己交差了。

其实现的代码也已经放到百度网盘上可以供参考。

链接:https://pan.baidu.com/s/17A37ISKT0tW3WWq2oXJASw 提取码:dgr6

上述代码仅供参考,优化部分还需完善。

6.总结

需要注意的是,对于不同的LCD,需要自己找到合适的大小的字体,这样才能看起来清楚。另外在实现的细节上需要注意的是最好不要在framebuffer上直接绘图,可以放到一个与framebuffer大小一样的数组中,叫做palette,也就是画板。当绘制一帧画面完成后,再刷新到framebuffer中,这是因为framebuffer是非cache的,操作起来会影响刷屏的帧率,看起来帧率会很低。

对于英文字库的显示、中文汉字的处理,有很多东西需要去拓展。其中汉字的抗锯齿问题就很值得研究学习,汉字模糊,汉字的锐化等等,万变不离其宗,其核心都是对像素的处理。LCD绘图,理解像素处理流程,所有的上层应用实现都非常好理解。

wpf计算字符大小占像素_LCD作为终端显示字符串的过程相关推荐

  1. wpf计算字符大小占像素_[读书笔记]《计算机科学速成课》——23 屏幕与2D图像显示...

    早期的文本任务通过打印机显示,因为屏幕分辨率较低,无法显示清晰的文字,而将计算结果的文字打印在纸上,有更高的对比度和分辨率,屏幕一般只用于跟踪程序的运行情况,比如寄存器的值,可以节约纸,并且屏幕更新很 ...

  2. opencv计算指定区域黑白像素占比

    如下在我们拿到二值化的图像之后,想要计算红框内黑白像素在该区域的占比.注意单通道的图像无法出现黑白以外的颜色. 上图为我们拿到的红色区域二值化之后的图像.我们通过遍历该区域所有像素来判断.若值为255 ...

  3. C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别

    字符数组的长度计算:必须以终止符'/0'作为边界,但对字符数组赋值时,有两种方式: 1: 定义时用字符初始化 (1)char chs[7] = {'a', 'c', '0', 'z', '3','d' ...

  4. c语言sizeof测量字符组长度,C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别...

    1:定义时用字符初始化 (1)char chs[7] = {'a', 'c', '0', 'z', '3','d'}; // 长度为6 上式等价于: (2)char chs[7] = {'a', 'c ...

  5. c语言字符数组的实际长度,C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别...

    1:定义时用字符初始化 (1)char chs[7] = {'a', 'c', '0', 'z', '3','d'}; // 长度为6 上式等价于: (2)char chs[7] = {'a', 'c ...

  6. 中英文字符大小和文本边界问题

    中英文字符大小和文本边界问题 也不知道是楼主的问题还是CSDN的问题,楼主最近的博客在贴代码的时候出现了问题,明明把代码贴进去了,还是没有代码的效果,好吧.先这样吧,过几天再看看到底是啥情况. ASC ...

  7. C#网络编程(四、Socket中英文字符大小和文本边界问题)

    转自:http://blog.csdn.net/shanyongxu/article/details/51190820,本人学习受益匪浅,楼主把重点都标记出来了,请点击链接查看原文,尊重楼主大大版权. ...

  8. Android 计算Bitmap大小

    今天使用LruCache写demo的时候,要获取Bitmap的大小 于是就用到了 return bitmap.getRowBytes() * bitmap.getHeight();// 获取大小并返回 ...

  9. 在 JavaFX 中,如何计算文本所占像素的宽度

    在 JavaFX 中,如何计算文本所占像素的宽度 注意事项 算法 代码 计算单行文本的像素宽度 计算文本框尺寸   JavaFX 的恼人之处在于很多基本的操作都要自己亲力亲为.有些时候,我们希望 Te ...

最新文章

  1. SAP 金属行业实施项目的GAP之Metall Balance
  2. 《Cloud Native Infrastructure》CHAPTER 7 (1)
  3. mysql相关文献及翻译_MySQL数据库管理外文翻译文献中英文.doc
  4. ajax中res和req,javascript – 来自AJAX调用的res.redirect
  5. centos编译安装LNMP
  6. 央视报道:荣耀智慧屏或搭载华为鸿蒙系统
  7. IA-32 System-Level Registers and Data Structures
  8. PHP用socket连接SMTP服务器发送邮件
  9. 8255工作方式一A口和B口输出
  10. C++ 从函数参数中获取指针 指针传递
  11. 《R in Action》读书笔记(2)
  12. jq.$post传递参数给php,通过URL参数post传递的实现方式 PHP/Javascript
  13. capslock亮灯是小写_当CapsLock灯亮时,表示输入的字母是小写字母。
  14. 图灵的遗产和后继者们的责任
  15. hhkb mac设置_HHKB 键盘 使用攻略 Karabiner
  16. Dreamweaver CS6破解教程[序列号+破解补丁]
  17. elasticsearch 使用
  18. 什么是外包公司,外包公司与互联网公司的区别
  19. Couldnot load Project The file couldn‘t be opened
  20. 数据中台建设(三):数据中台架构介绍

热门文章

  1. 在 Mac 上通过 Docker 运行 Asp.net Core 简易教程
  2. Cucumber+Rest Assured快速搭建api自动化测试平台
  3. 微信企业号开发[二]——获取用户信息
  4. C# DateTime简单的定时器用法
  5. eval()解析JSON
  6. USACO2.11 The Castle hdu1198
  7. 在C#中运用 SQLite
  8. 【转】DATAGRIDVIEW控制
  9. 聊聊内卷之下,直博和读完硕士再读博该怎么选择?
  10. 为什么一个字节定义成8位?