技术标签: linux点阵ascii像素字体
起因:
早在阅读tslib源代码时就注意到里面有font_8x8.c和font_8x16.c两个文件(后来才得知,它们来自Linux内核,具体目录是./drivers/video/console),它们包含了在屏幕上显示所需的所有字符(当然,是可打印字符),由此也看了一下tslib显示字符的代码。对将来在触摸屏上显示汉字有所帮助,——这是后话,暂且按下不提。
上面所说的字符当然是ASCII码了,这种编码学过计算机的人可能会很熟悉,就不多讲了。本文所述者,就是通过ASCII码字库文件(网上有下载)和上面提到的其中之一的文件在终端上显示ASCII字符。这也为研究汉字显示打下基础(此为假话,写文章及做作所需也,实际上本文作者是先研究汉字显示再研究ASCII码显示的,勿模仿,切切)。
本文中使用的字库是8x16,每个字符占用内存空间为16字节(后面不再提及),文中显示字符所做工作有下面几步(显示汉字也差不多,当然,这又是后话 ):
1、打开字库文件(似乎是废话);
2、计算出要打印的字符在字库文件中的偏移量(亦即网上所说的“寻址”);
3、将这个偏移地址的数据(16字节)读取缓冲区中;
4、显示这个缓冲区,为1者打印,为0者留空。(由于是在终端上显示,因此,可以使用如“#”、“*”等字符代替。)
先说说如何找到某个字符在字库文件中的偏移量。字库里的字符排序是符合ASCII码顺序的,而每个字符占16字节,因此,将要打印的字符与16相乘,便得到这个字符在字库中的位置了,这个位置之后的16个字节的数据,就是这个字符了。比如大写字母“A”,十六进制是0x41(“A”还是十进制的65、八进制的101,其实都是一回事),它与0x10(十进制的16)相乘,得到0x410(计算机中使用十六进制十分方便,对于某些试题要求计算出某地址的十进制,我表示不理解,既不直观,又不方便,还容易出错)。使用十六进制编辑器(用UE相信会更方便些)查看这个偏移量,会发现有如下数据:
$ hexdump -C ../HZK/ASC16 | grep 410
00000410 00 00 10 38 6c c6 c6 fe c6 c6 c6 c6 00 00 00 00 |...8l...........|
所谓的字库,里面就是一些二进制数据。我们看看上面得到“A”的16个字节数据显示效果是怎样的。将上面的十六进制数据按二进制输出,一个字节一行,共占16行,如下:
00000000
00000000
00010000
00111000
01101100
11000110
11000110
11111110
11000110
11000110
11000110
11000110
00000000
00000000
00000000
00000000
不直观,将出现0的地方留空,则变成如下形状(受网页影响,为美观起见进行调整,虽非实际中二进制所示,但形状是一致的):
1
111
11 11
11 11
11 11
1111111
11 11
11 11
11 11
11 11
上面的便是传说中的“A”了。
下面就用代码读取字库信息,并显示出来。完整代码如下:
/***************************************************
源代码文件编码:ANSI
测试环境编码:zh_CN.UTF-8、zh_CN.gd2312
* ************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef DEBUG
#define debug(fmt, ...) printf(fmt, #__VA_ARGS__)
#else
#define debug(fmt, ...)
#endif
void display_font_ascii(
char *asc)
{
int i, j;
debug(
"=================/n");
for(i=
0;i<
16;i++)
{
for(j=
0;j<
8;j++)
{
/* 逐位相与,为1者打印“*”,否则打印空格 */
if(asc[i] & (
0x80>>j))
printf(
"*");
else
printf(
" ");
}
printf(
"/n");
}
debug(
"=================/n");
}
int main()
{
int i;
unsigned
char *p;
unsigned
char asciicode[] =
"Ab";
unsigned
long offset;
FILE *asc;
char ascii[
16];
if((asc=fopen(
"ASC16",
"rb"))==NULL)
{
perror(
"Can't Open ASC16");
exit(
0);
}
/* ASCII字库文件 */
for (i =
0; i <
sizeof(asciicode)-
1; i++)
{
debug(
"%c %x/n", asciicode[i], asciicode[i]);
/* 打印数值 */
offset = asciicode[i]*
16;
debug(
"offset: %x/n", offset);
/* 打印偏移量 */
fseek(asc,offset,SEEK_SET);
fread(ascii,
16,
1,asc);
/* 读取16字节 */
display_font_ascii(ascii);
/* 显示 */
}
fclose(asc);
return
0;
}
由于是示意性代码,不必纠结于代码优化、代码风格等等问题。效果(同样进行了调整)如下:
$ ./a.out
*
***
** **
** **
** **
*******
** **
** **
** **
** **
***
**
**
****
** **
** **
** **
** **
** **
*****
还有另一种方法,不读取字库,而是将所有的字符存放于某个数组中,比如像font_8x16.c文件中的fontdata_8x16数组。这里假设数组为ascii_code,那么,上面的代码只需修改一小部分,如下:
for (i = 0; i < sizeof(asciicode)-1; i++)
{
debug("%c %x/n", asciicode[i], asciicode[i]);
offset = asciicode[i]* 16; // 寻址
p = ascii_code+offset; // 查找字符在ascii_code数组中的偏移量
debug("offset: %x/n", offset);
display_font_ascii(p);
}
效果是一样的,所不同的是,前一种方法需要读取字库文件,后一种方法直接在内存中读取,完整的ASCII码占用空间为4KB。不过,ASCII中可打印的字符共96个(经过认真数那些可打印的字符,发现实际上是95个(即32号到126号),这里将127号算上了,具体的请搜索一下ASCII),占用空间为96*16,即1536字节。由于前面0x20(即32)个字符在显示中没有用到,因此是可以去掉的,这样一来,寻址方式又稍有不同,如下:
for (i = 0; i < sizeof(asciicode)-1; i++)
{
debug("%c %x/n", asciicode[i], asciicode[i]);
offset = (asciicode[i] - 0x20 )* 16; // 寻址
p = ascii_code+offset; // 查找字符在ascii_code数组中的偏移量
debug("offset: %x/n", offset);
display_font_ascii(p);
}
由于文中涉及知识、代码、字库文件都可以在网络上找到,因此文中就不提供下载了。
资料:
1、ASCII码字库,有多种形式,如8*16、8*12,名称为ASC12、ASC16,搜索一下就能找到。
2、“字库数组”,可以在Linux内核源代码的./drivers/video/console目录下找到很多相关代码文件,如font_8x8.c、font_8x16.c、font_sun8x16.c等等。像font_8x16.c文件,代码中说是由cpi2fnt这个东西产生的,但搜索一下,没什么介绍,英文的又不想去看,对这个东西也就不了解了。
3、可以搜索一下字库生成工具,用这些工具可以生成需要的字库。
文章浏览阅读1.2w次,点赞4次,收藏18次。 1.使用斜杠划分路径,每个文件都有具体的路径。 @echo offdir /s/b *.* > 文件名.txtexit 2.使用树状图表示文件结构,层次清晰。 @echo offfor /f "delims=" %%i in ('cd') do set "..._导出文件夹中所有文件名 包括子文件夹
文章浏览阅读544次,点赞5次,收藏8次。可以放心的是,这四款软件都经过了安全测试,能够保证文件的安全性,并且能够兼容多种操作系统,在不同的平台上使用。2、在压缩文件名和参数窗口中,按需设置相关参数,比如设置压缩文件名、压缩文件格式,压缩方式等。* 压缩效率:压缩效率较高,可以快速地完成文件压缩,同时提供了多种压缩级别供用户选择。* 压缩效率:压缩效率较高,可以快速地完成文件压缩,并提供了多种压缩级别供用户选择。3、再选择【压缩等级】,极限压缩压缩的文件可以到达最小,同时压缩后的质量最低。4、设置好参数后点击【立即压缩】,还可以选择压缩配置。_压缩软件 csdn
文章浏览阅读1.6k次。从本文开始,按照AI策略开发的完整流程(共七步),上手在BigQuant平台上快速构建AI策略。_bigquant
文章浏览阅读4.7w次,点赞42次,收藏147次。git 如何把master分支代码合并到自己的分支master分支的代码领先自己的分支,git 如何把master分支代码合并到自己的分支1.首先切换到主分支git checkout master2.使用git pull 把领先的主分支代码pull下来git pull3.切换到自己的分支git checkout xxx(自己的分支)4.把主分支的代码me..._master 分支可以合到其他分支吗
文章浏览阅读169次。这类问题在蓝桥杯中经常出现,没有固定做法,一般难度不算大。一般做法是按照题目要求模拟出来,一般不会涉及最优化问题。_蓝桥杯枚举问题
文章浏览阅读112次。解决方法:HTTPRIO1的属性---HttpWebNode--UseUtf8InHeader设置为true 代码片断:function TLoginManager.Get_LoginManagerSoap: ILoginManagerSoap;const defSvc='LoginManager'; defPrt='LoginManagerSoap';var R..._delphi7中调用c#开发的web service时,传入的每个汉字变成了三个问号???
文章浏览阅读1.4k次。如图使用IDEA打开java web项目,出现了上图各种包找不到,出现这种原因的是没有关联tomcat的jar包,如何解决这样的问题第一步:第二步:-> 第三步:此时当前java web项目已经关联了tomcat,但此时还是出现找不到相关包,接下来还是要继续关联tomcat 里的jar包,具体操作如下到这里就完成了对tomcat jar包的依赖,返回刚才找不到包的文件 按下 alt+enter 导包就可以了。这样就可以了。具..._idea连接tomcat红方块
文章浏览阅读5.1k次,点赞3次,收藏5次。执行netca /silent /responsefile /datas/oracle/response/netca.rsp报错UnsatisfiedLinkError exception loading native library: njni11[oracle@oracle ~]$ netca /silent /responsefile /datas/oracle/response/netca.rspUnsatisfiedLinkError exception loading native libr_unsatisfiedlinkerror exception loading native library: njni11
文章浏览阅读429次。在智慧船舶自动化信息服务平台的研究中,常规的服务平台在运行过程中存在服务节点失效的情况,降低了用户体验。面对这一问题,图扑软件提出基于云计算虚拟化技术的智慧船舶自动化信息服务平台设计。效果展示通过 HT 实现可交互式的 Web 三维场景,可进行缩放、平移、旋转、翻转,场景内各设备可以响应交互事件。结合 HT 引擎强大的渲染能力,保证场景在 Web 中高效流畅地加载运行并保证优秀的可视化效果。2D、3D 无缝衔接,完美融合。注重细节刻画,点击相对应的设备能显示其作业等信息。船舶信息可._图扑综合自动化
文章浏览阅读481次。php实现短信验证的方法:首先接入短信服务;然后在网站信息提交页面请求发送信息;接着服务器向短信服务提供商通信,提交发送请求;最后短信服务提供商通过运营商将信息发送到用户的手机中。php实现短信验证的方法:第一、实现php手机短信验证功能的基本思路1、要找到短信服务提供商,接入短信服务2、在网站信息提交页面请求发送信息3、服务器向短信服务提供商通信,提交发送请求4、短信服务提供商通过运营商将信息发..._php短信验证码校验 代码实现
文章浏览阅读7.4k次,点赞19次,收藏62次。1.从/dev目录说起从事Linux嵌入式驱动开发的人,都很熟悉下面的一些基础知识比如对于一个char类型的设备,我想对其进行read wirte 和ioctl操作,那么我们通常会在内核驱动中实现一个file_operations结构体,然后分配主次设备号,调用cdev_add函数进行注册。从/proc/devices下面找到注册的设备的主次设备号,在用mknod /dev/char_de..._cdev、misc以及device三者之间的联系和区别
文章浏览阅读3k次。CC:对寄存器的操作不能使用类似51单片机的方法,如P1.1,定义了寄存器的地址,使用结构体对其进行操作,定义在头文件iodefine.h可以找到,如下:结构体定义地址定义CA CX可以使用类似51单片机一样的对寄存器的操作方法,其在macrodriver.h中有预处理命令:#pragma sfr预处理命令所以换编译器时代码需要对相关定义进行修改。..._瑞萨cx和cc