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

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.显示原理

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

b9e9d76a0638ddf71e16f68c189f9680.png

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

8f814c592e65617d87cc7192a46bec87.png

而这些像素的亮度决定了最后显示在屏幕上的效果。像素深度(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填充白色像素点。

88eb6154c477e26af155fd5c2a26e0cd.png

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

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

4.嵌入式上汉字处理

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

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

5.结果验证与展示

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

f5bdddee803397f89c0752e64d45dab7.png

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

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

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

6.总结

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472745.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中对象作为参数_java中对象引用,特别作为参数时候注意事项

1、基础知识1Byte8bitByte和byte一个是对象,一个是基本数据类型而已,都是8bit2、java中对象引用和值传递:(1)、java中若一对象当作参数就是相当于,将变量对应的指向的地址内容传递进去了如下面代码:public class Test …

商城简单类图

转载于:https://www.cnblogs.com/stit/p/4125095.html

Java 自定义排序 Comparator

语法: class 比较器名 implements Comparator 重写 int compare(Object o1, Object o2) import java.util.*;class comparatorDemo implements Comparator {public int compare(Object o1, Object o2) {String a, b;a (String) o1;b (String) o2;return b.compar…

交换机的基本配置实验报告_无线网络设计配置即实验报告

工程师ACK接到一个小型图书馆的网络组建项目,根据目前流行的网络组建以及项目地点的使用需要便捷性,采用AC控制的瘦AP模式。不需要AC来管理网络的AP是胖AP需要单独配置,有多少个AP就要配置多少次。组建模式:一楼划分20个VLAN,二楼…

java异步处理同步化_java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring EventListener,超时处理和空循环性能优化...

异步转同步业务需求有些接口查询反馈结果是异步返回的,无法立刻获取查询结果。正常处理逻辑触发异步操作,然后传递一个唯一标识。等到异步结果返回,根据传入的唯一标识,匹配此次结果。如何转换为同步正常的应用场景很多&#xff0…

PHP上传文件大小限制的问题(转)

在用PHP进行文件上传的操作中,需要知道怎么控制上传文件大小的设置,而文件可传大小是受到多种因素制约的,现总结如下:1、php.ini:upload_max_filesize 所上传的文件的最大大小。默认值2M。2、php.ini:memory_limit 本指令设定了一…

Java 集合框架(List、Set、Map、Iterator、Stack、Properties)

文章目录1. ArrayList2. LinkedList3. HashSet4. TreeSet5. Iterator、ListIterator6. HashMap7. TreeMap8. Stack9. Properties 类读写简单 数据库相关文献:https://www.runoob.com/java/java-collections.html 1. ArrayList 类似动态数组 ArrayList al new Arr…

js获取当前url_javascript如何获取当前URL的主机名?

在javascript中可以使用location对象的hostname属性或者host属性来获取当前URL的主机名,下面本篇文章就来带大家认识这两种属性,希望对大家有所帮助。使用location hostname属性location hostname属性是用于返回当前URL的主机名;它会返回一个…

java访问数据库方式_java数据库访问(二)—JDBC方式(配合连接池)

上文记录了最基础的JDBC连接数据库的方法,但能看出一个问题,就是要不断的重复去创建connection和关闭connection,如果在对数据库的访问比较频繁的情况下,这种处理方式方式在性能方面是不合适的,下面使用JDBC配合数据库…

超频真的不难!G3258超频4.5GHz全攻略

奔腾G3258搭配主板详解【pconline 应用】目前DIY市场上最火热的装机组合莫过于奔腾20周年纪念版处理器G3258搭配B85芯片组主板,只要通过适当的超频,相对较低投入也能来不错的性能体验,因此在奔腾G3258还没上市时,业界对其充满期待…

python算法入门_GitHub标星2.6万!Python算法新手入门大全

问耕 发自 凹非寺量子位 出品 | 公众号 QbitAI今天推荐一个Python学习的干货。几个印度小哥,在GitHub上建了一个各种Python算法的新手入门大全,现在标星已经超过2.6万。这个项目主要包括两部分内容:一是各种算法的基本原理讲解,二…

Java enum枚举

文章目录1. 枚举例子2. 接口的实现3. 枚举中定义抽象方法enum 定义了枚举类型,其继承于 Enum 枚举类 1. 枚举例子 import java.util.EnumMap; import java.util.EnumSet; import java.util.Iterator; import java.util.Map;class EnumDemo {public enum Color{RED…

mysql写什么不同_mysql - 编译配置PHP时,两种配置写法有什么不同

在编译PHP时,--with-扩展库DIR--enable-扩展库这两种配置有什么不同回复内容:在编译PHP时,--with-扩展库DIR--enable-扩展库这两种配置有什么不同很明显是取值的不同:with 后面可以为空,即默认值;可以是路径;可以是功能名称enable 后面不能有…

Java入门到精通——基础篇之static关键字

一、概述static 关键字是声明静态变量,静态方法用的。static的含义是属于类且不属于类对象的变量和函数。二、static的产生。在创建对象的时候除非用new创建那个类的对象,否则实际上并没有获得任何对象只有当执行new来创建对象时数据存储空间才被分配&am…

Java 给编译器看的注释--Annotation

文章目录1. 系统内建的Annotation2. 自定义Annotation3. Retention4. 反射 与 Annotation5. Target6. Documented7. Inherited将配置直接写入到程序之中:Annotation 1. 系统内建的Annotation Override,Deprecated,SuppressWarnings 等 cla…

kafka启动_Kafka安装部署——单节点

1.1 Kafka的单节点部署在实际的工作中,经常使用Kafka作为消息队列,然而并不是每一种业务场景都需要集群版的Kafka,有时单节点的Kafka就能满足了业务的需求。以下就是单节点kafka的部署流程:1.1.1 安装包下载从Kafka官网下载最…

mysql怎么多表备份_学习MySQL多表操作和备份处理

【IT168 服务器学院】前面我们熟悉了数据库和数据库表的基本操作,现在我们再来看看如何操作多个表。多表操作在一个数据库中,可能存在多个表,这些表都是相互关联的。我们继续使用前面的例子。前面建立的表中包含了员工的一些基本信息&#xf…

Maven 入门 (1)—— 安装

Maven 入门 (1)—— 安装 http://blog.csdn.net/kakashi8841/article/details/17371837 1、下载maven安装包 http://maven.apache.org/download.cgi 2、基于Unix的操作系统(Linux、Solaris 和 Mac OS X) 解压上面下载的包&#xf…

中文新闻分类 数据集_三亚试点用大数据推行垃圾分类:刷卡扔垃圾,分类有奖励|界面新闻...

文丨海南日报 高懿 周月光10月19日电 ,垃圾分类如何推行?三亚市引进智能装备,在6个社区开展试点,运用大数据分析,通过行为激励,引导市民积极配合垃圾分类。19日上午,记者现场采访试点社区垃圾分…

为什么a*算法采用哈密尔顿距离作为启发函数比不在位数为启发函数的性能要好?_KDD2019: 使用神经网络为A*搜索算法赋能 --以个性化路径推荐为例...

本文系 KDD2019 论文的解读:Wang, Jingyuan, Ning Wu, Wayne Xin Zhao, Fanzhang Peng, and Xin Lin. "Empowering A* Search Algorithms with Neural Networks for Personalized Route Recommendation." InProceedings of the 25th ACM SIGKDD Internati…