第14章汉字的显示与放大.ppt

上传人:本田雅阁 文档编号:2986220 上传时间:2019-06-20 格式:PPT 页数:50 大小:1,010.02KB
返回 下载 相关 举报
第14章汉字的显示与放大.ppt_第1页
第1页 / 共50页
第14章汉字的显示与放大.ppt_第2页
第2页 / 共50页
第14章汉字的显示与放大.ppt_第3页
第3页 / 共50页
第14章汉字的显示与放大.ppt_第4页
第4页 / 共50页
第14章汉字的显示与放大.ppt_第5页
第5页 / 共50页
点击查看更多>>
资源描述

《第14章汉字的显示与放大.ppt》由会员分享,可在线阅读,更多相关《第14章汉字的显示与放大.ppt(50页珍藏版)》请在三一文库上搜索。

1、2019/6/20,1,第十四章 汉字的显示与放大,汉字的编码 用作图方式显示和放大汉字 直接写VRAM显示汉字,2019/6/20,2,第一节、汉字的编码,汉字的主要编码 区位码 国标码 机内码 字形码 地址码,2019/6/20,3,汉字数目众多(康熙字典收录47000多个),但最常用的高频字仅约100个,常用字约3000个,次常用字约4000个,罕见字约8000个,其余都是死字。 1981年,我国公布了通讯用汉字字符集(基本集)及其交换码标准GB2312-80方案,把高频字、常用字、次常用字汇集起来组成了汉字基本字符集(共6763个汉字)。,概 述,2019/6/20,4,上述基本字符集

2、由三部分组成: 一级汉字 (使用频度较高的3755个汉字,按拼音排序) 二级汉字 (使用频度略低的3008个汉字,按部首排序) 西文字符、数字、图形符号 (700多个非汉字字符) 为管理方便,将上述所有字符排列在了一个94*94的表格中,一、汉字的区位码,2019/6/20,5,一、汉字的区位码,2019/6/20,6,表中每一行为一个区,每一列为一个位。 汉字(字符)在表中的区号和位号构成了汉字的区位码。 例如: “啊”在16区01位,故“啊”的区位码是1601 “大”在20区83位,故“大”的区位码是2083 说明:区位码常以十六进制表示, 如:1453H,一、汉字的区位码,2019/6/

3、20,7,二、汉字的国标码,计算机要处理汉字,必须给每个汉字一个唯一的编码,这些编码是国家机构按统一标准编排的,故称国标码。 英文字符是用一个字节编码的,即ASCII码,而汉字数量众多,需要用两个字节才足以完成编码,所以汉字(含前15区的符号)的国标码是两个字节。,2019/6/20,8,二、汉字的国标码,国标码的两个字节是这样来的:将汉字(含前15区的符号)的区号和位号分别加上32 并各用一个字节表示出来。 例如: “啊”的区号是16,位号是1,其国标码是: 00110000 00100001 “大”的区号是20,位号是83,其国标码是: 00110100 01110011,2019/6/2

4、0,9,二、汉字的国标码,提示: 汉字区号、位号最大是94 94 + 32 = 126,不超过127 如:设94区94位有汉字,其国标码应为: 01111110 01111110 结论:国标码的两个字节的最高位都是0,2019/6/20,10,三、汉字的机内码,每个汉字都有唯一一个国标码,按说可以用计算机处理汉字了,但不幸的是,计算机不仅要处理汉字,还要处理英文字符,而汉字国标码和英文编码是存在冲突的。 例如:“大”的国标码是:00110100 01110011,如果把国标码的这两个字节直接存储到计算机中,则系统很可能把它们当做两个英文字符(字符4和字符i),因此计算机内部不能存储国标码。,2

5、019/6/20,11,三、汉字的机内码,为避免和英文的ASCII码混淆, 存储汉字前,总是先把国标码两个字节的最高位都改为1然后再存储,这样就由国标码变成了机内码(计算机内部实际存储的汉字编码)。 如: “大”的国标码是: 00110100 01110011 机内码是: 10110100 11110011,2019/6/20,12,三、汉字的机内码,注意:存储机内码时,总是把区号对应的字节存储在低字节,而把位号对应的字节存储在高字节。如:,“大”的机内码是:10110100 11110011 对应区号 对应位号,低字节,高字节,2019/6/20,13,三、汉字的机内码,机内码和区位码的转换

6、关系: 区号 = 机内码的低位字节 160 位号 = 机内码的高位字节 160 解释说明: 机内码是在国标码的基础上将两字节最高位都变为1而得来,相当于两个字节各加了128 而国标码是由区位码各加32而来,2019/6/20,14,四、汉字的字形码,汉字的形状各不相同。为在计算机中显示汉字,通常都是先把每个汉字的形状记录下来,形成字形码 例如: 16点阵宋体字库中“大”字的字形码是这样来的:,2019/6/20,15,四、汉字的字形码,画一个16*16的表格,在上面写一个宋体“大”。接下来,从左上角的小方格开始记录“大”字的形状,若小方格被“大”字覆盖,则记为1,否则记为0。,2019/6/2

7、0,16,四、汉字的字形码,将所有汉字(符号)的16点阵宋体字形码按顺序汇集到一起就是16点阵宋体字库 字库中存有区位表中所有汉字(符号)的字形码。当需要显示某汉字(符号)时,先从字库中调出该汉字的字形码,再在屏幕上显示出来。,2019/6/20,17,四、汉字的字形码,字库有很多种,根据点阵大小不同和汉字字体的不同,可把字库分为: 16点阵宋体字库、16点阵黑体字库、16点阵仿宋字库、16点阵楷体字库 24点阵宋体字库、24点阵黑体字库、24点阵楷体字库 48点阵 60点阵 ,点阵数越大,笔画越平滑,点阵数越小,锯齿越严重。,2019/6/20,18,五、汉字的地址码,对于16点阵的字库,

8、一个汉字的字形码在字库中存储的起始位置是: offset=(94*(qh-1)+wh-1)*32 其他点阵(设为S点阵): offset=(94*(qh-1)+wh-1)*S*S/8 汉字字形码在字库中的首地址称作该汉字的地址码,2019/6/20,19,第二节 作图法显示与放大汉字,在西文状态下显示汉字一般处理方法: 在中文操作系统中打开源程序将需要显示的汉字存入数组(存储的是汉字的机内码) 如:char p =“汉字显示技术”; 程序中 通过机内码计算汉字的区号和位号,从而获得地址码 打开字库文件,读取字形码 图形方式下画点,“点”出汉字 在西文DOS下编译、连接、执行,2019/6/20

9、,20,一、把汉字存入内存,在源程序中把要显示的汉字(一个或多个)存到内存中。 char p = “汉字显示技术”; 或: char *p = “汉字显示技术”; 存储源程序时,实际存储的是这些汉字的机内码 (正如英文字符要被转换为ASCII码) 运行程序时,机内码将被装入内存,2019/6/20,21,二、计算地址码,由机内码可计算出地址码: 从内存中取出一个汉字的机内码,用来计算区号qh和位号wh。 qh = *(p+i) -160; wh = *(p + i + 1) - 160; 计算该汉字的地址码 (设字库是S点阵) offset = (qh - 1)*94 + (wh - 1)*S

10、*S/8;,2019/6/20,22,三、从字库中获得字形码,#define S 16 /点阵数 #define HZK “d:tcfonthzk16f” char bufferS*S/8; /用来存字形码 if(fp = fopen(HZK, “rb“) = NULL) printf(“打不开字库文件n”); exit(0); fseek(fp, offset, 0); fread(buffer, S*S/8, 1, fp);,2019/6/20,23,四、画出汉字,设要在屏幕的(x,y)处显示该汉字,2019/6/20,24,要在屏幕上显示出汉字,需要对字型码中的每个字节进行处理,将每个字

11、节变成8个像素 编程思路: for(i = 0; i S*S/8 ; i+) /将第i个字节的字型码,画成8个点 ,四、画出汉字 (方法一),2019/6/20,25,四、画出汉字 (方法一),字形码的第i个字节,所决定的8个像素的起点是(x+(i%(S/8)*8, y+i*8/S)。 程序中要针对第i个字节的8个位依次进行判断和操作, 对于字形码为1的位,画出一个点 char mask = 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 ; for(j = 0; j = 7; j+) if(bufferi ,2019/6/20,26,故,循环处理

12、字形码每个字节的代码是: char mask = 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 ; for(i = 0; i S*S/8 ; i+) for(j = 0; j = 7; j+) if(bufferi /设置字间隔 ,四、画出汉字 (方法一),详细代码:s14_1_1. c,2019/6/20,27,四、画出汉字 (方法二),也可以针对点阵图中的每一像素来循环 可以算出, 图中第i行第j列的像素由字形码的第(S/8*i+j/8)字节决定,因此循环可写成: for(i = 0; i = S-1; i+) for(j = 0; j =

13、S-1; j+) if(bufferS/8*i + j/8) ,详细代码:s14_1_2. c,2019/6/20,28,五、汉字的放大,汉字的放大实际上就是把一个像素变成几个像素。例如,若将汉字放大2倍,则汉字的宽度和高度都要变成2倍,原来的一个像素要变成4个像素。 若要放大m倍,则要把1个像素变成m2个像素 for(k = 0; k m; k+) for(n = 0; n m; n+) putpixel(x+m*j+k, y+i*m+n, color);,详细代码:s14_2. c,2019/6/20,29,实 训,1、编写程序,在图形状态下显示自己的姓名,然后再放大二倍显示。 2、请针对

14、打印字库修改例14.1、14.2 说明:字库分为显示字库和打印字库两种,区别有两点: 显示字库中每个字的字形码是按行存放的(先存第一行,再存第二行),而打印字库中的字形码是按列存放的(先存第一列,再存第二列) 打印字库去掉了115区的符号,从1区开始就是汉字,2019/6/20,30,第三节 直接写VRAM显示汉字,直接写屏,实际上就是图形方式下,把要显示汉字的点阵信息直接存入VRAM相应的位面上,写的过程就是显示的过程。 直接写VRAM显示汉字比作图法显示汉字快很多。 两种方法: 利用定序器直接写VRAM 用方式寄存器和位屏蔽寄存器直接写VRAM,2019/6/20,31,一、利用定序器直接

15、写VRAM,VGA显示适配器中的定序器中,有5个寄存器共用一个口地址0x3c5,使用的是哪一个寄存器,是由索引寄存器(口地址0x3c4)中的索引值决定的。,2019/6/20,32,一、利用定序器直接写VRAM,数据送入口地址为3c5的寄存器过程:,2019/6/20,33,一、利用定序器直接写VRAM,要选择颜色位面写允许寄存器,应向索引寄存器送入2:outportb(0x3c4, 2); 颜色位面写允许寄存器的值(低4位)决定着VRAM的4个位面是否可写。如:,2019/6/20,34,一、利用定序器直接写VRAM,直接写VRAM显示汉字,就是通过“颜色位面写允许寄存器”的控制把字形码写到

16、指定位面上。 方法:把汉字的颜色写入“颜色位面写允许寄存器” outportb(0x3c5, color); 作用:有选择地把字形码写入一些位面,写入哪些位面由color决定。,2019/6/20,35,一、利用定序器直接写VRAM,如:设字形码第一个字节为10XXXXXX (下同) 若color为WHITE(15, 二进制: 1111), 则: 字形码将写入4个位面,字形码为1的像素将显示为白色,为0的像素显示为黑色,2019/6/20,36,一、利用定序器直接写VRAM,若color值为BLUE(1, 二进制: 0001), 则: 只写位面0,其余三个位面保持原数据不变(若原数据都是0,对

17、于第一点,像素将是蓝色,第二点为黑色) 原来数据不是0(背景不是黑色)呢?,2019/6/20,37,一、利用定序器直接写VRAM,void disphz(int x, int y, char*buffer, int color) /x 、y是汉字显示坐标,buffer是字形码首址 char far *p; int i, j; p = (char far*)(0xa0000000 + 80*y + x/8); outportb(0x3c4, 2); outportb(0x3c5, color); for(i = 0; i S; i+) /一个汉字要显示S行像素 for(j = 0; j S/8

18、; j+) /每行要写S/8个字节 *(p + 80*i + j) = bufferS/8*i + j; outportb(0x3c5,0xf); ,每行640像素,80字节,因此,要求显示汉字的横坐标必是8的倍数,课堂演示:14_1 c,2019/6/20,38,一、利用定序器直接写VRAM,上面程序仅在背景色为黑(四个位面的原数据都是0 ) 的情况下能按指定颜色显示一个汉字。 若背景色不是黑色(原数据不是0 ) ,显示的汉字通常不是指定颜色。若要在任意背景下都显示指定颜色,需要对4个位面的数据都改写。,2019/6/20,39,一、利用定序器直接写VRAM,例如: 设字形码第一个字节为10

19、XXXXXX (下同) 要将汉字显示成淡绿色(color:10,二进制值:1010),则: 字形码为1时,四个位面的数据必须是1010,以便显示一个淡绿色的点 位面3、1要写成1 位面2、0要写成0,2019/6/20,40,一、利用定序器直接写VRAM,例如: 要将汉字显示成淡绿色(color:10,二进制值:1010),则: 字形码为0时,所有位面上该位的值均应保持原值 位面3、1不变 位面2、0不变,2019/6/20,41,一、利用定序器直接写VRAM,也就是: 对于位面3和位面1, 字形码为1的位,要写入1 字形码为0的位,保持原值 对于位面2和位面0 字形码为1的位,要写入0 字形

20、码为0的位,保持原值。 因为向VRAM写字形码时,不是一位一位地写,而是每次向一个位面写一个字节(4个位面逐个写)。,2019/6/20,42,一、利用定序器直接写VRAM,如何区分这两类位面? char mask = 0x01,0x02,0x04,0x08; for(n = 0; n 4; n+) if(color & maskn != 0) /对位面3和位面1的操作 else /对位面2和位面0的操作,2019/6/20,43,一、利用定序器直接写VRAM,关键代码: char mask = 0x01,0x02,0x04,0x08; for(n = 0; n 4; n+) if(color

21、 原理: 字形码 01110010 字形码 01110010 字形码取反 10001101 | 原值 00100101 & 原值 00100111 最终值 01110111 最终值 00000101,详细代码参阅:s14_3. c,2019/6/20,44,二、用方式寄存器和位屏蔽寄存器直接写VRAM,VGA显示适配器中的图形控制器中有9个寄存器共用一个口地址0x3cf,选择其中一个寄存器进行操作的方法是向索引寄存器(口地址0x3ce)中送入一个索引值 这里需要的是方式寄存器和位屏蔽寄存器,2019/6/20,45,二、用方式寄存器和位屏蔽寄存器直接写VRAM,1、方式寄存器 方式寄存器决定着

22、读写VRAM的方式,我们这里只用到写 写方式有三种,由寄存器最后两位决定: D1 D0 0 1 用锁存器的内容写 1 0 将CPU中数据的后四位(D3、D2、D1、D0)分别写入位面3、位面2、位面1、位面0。注意:当位屏蔽寄存器中对应的位为0时,该位的数据被屏蔽(不写) 1 1 不用,2019/6/20,46,二、用方式寄存器和位屏蔽寄存器直接写VRAM,2、位屏蔽寄存器 该寄存器对要写到VRAM中的数据位进行屏蔽,若位屏蔽寄存器某位为1,则写到VRAM中该位的数据是CPU的数据,否则写进去的是锁存器中的数据 如果在进行写操作前先进行读操作,使锁存器备份一下原来的数据,然后再进行写操作,则相

23、当于只把对应于位屏蔽寄存器中“1”位的数据改写了,而对应于“0”的数据是不变的。,2019/6/20,47,二、用方式寄存器和位屏蔽寄存器直接写VRAM,例如:在锁存器已备份好原来数据的情况下 若: 位屏蔽寄存器的值为 : 1 1 0 0 0 0 1 0 要写的数据是: * * * * 1 0 1 0 锁存器中的数据(VRAM某地址处4个位面的原数据)是: 位面3原值 0 1 1 0 1 0 1 1 位面2原值 1 1 0 1 1 1 0 1 位面1原值 0 1 0 1 0 1 0 1 位面0原值 0 0 0 1 1 0 0 0 则向该处写一个字节(*1010)后,4个位面的值变为: 位面3值

24、 1 1 1 0 1 0 1 1 位面2值 0 0 0 1 1 1 0 1 位面1值 1 1 0 1 0 1 1 1 位面0值 0 0 0 1 1 0 0 0,锁存器中的数据,2019/6/20,48,二、用方式寄存器和位屏蔽寄存器直接写VRAM,上面的操作: 对于位屏蔽寄存器中为1的位,数据的后四位将分别写到4个位面上,这四位数据恰好决定了一个像素的颜色 对于位屏蔽寄存器中为0的位,4个位面保持原来的数据不变,意味着屏幕保持原来的颜色不变 因此,要在屏幕上显示汉字,可: 将汉字颜色作为要写数据的后四位 将字形码的每个字节分别送入位屏蔽寄存器 将颜色值写入VRAM。,2019/6/20,49,

25、二、用方式寄存器和位屏蔽寄存器直接写VRAM,程序代码: 前面讨论的是把汉字显示成某颜色,背景色不变。 若需要取消背景色,代之以指定颜色作为底色,则需要添加如下代码: t = *(p + 80*i + j); outportb(0x3ce, 8); outportb(0x3cf, bufferS/8*i + j ); /屏蔽字形码为1的位 *(p + 80*i + j) = bkcolor; /bkcolor为背景色,程序代码参阅:s14_4_1. c,详细代码参阅:s14_4_2. c,2019/6/20,50,实 训,3、将例14_3改写为能输出汉字字符串的函数 4、将例14_4改写为能用打印字库输出汉字字符串的函数 5、改写第12章(作图)实训4的程序,利用直接写VRAM的方法显示所需要汉字 原题目修改如下: 利用输入重定向从文件读入10名学生的姓名和成绩(数学、英语、计算机),画出总分前三名的直方图(标上姓名),用圆饼图画出平均分在各分数段的比例(不及格、60-69,70-79,80-89,90-100),图形中要有图例。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1