摘要:本文叙述了汉字库的结构及汉字点阵信息的获得方法,并用VisualBasic5.0进行编程,调用UCDOS中48*48(48行乘48列)点阵的汉字库,获取汉字点阵数据,显示在文本框中,同时在图片框中用画点的方法把该汉字画出来。这是15年前自己写的一篇论文,好像还有参考价值,特收录在此。
1.48*48点阵汉字库的结构 大家在计算机屏幕上看到的汉字是由一系列的点构成的,如果用针式打印机把汉字打印在纸上,可以更清楚地看出是由一组黑点组成,这组黑点可能是24*24的点阵,如果是16*16的点阵看得就更清楚,如果是48*48点阵,因为单位面积的点数增加,就看不出是由点组成的汉字了。计算机在显示或打印汉字时要调用汉字库。 因为每个字节(8位的二进制数)数据可以描述8个点,(1代表黑,0代表白),所以用6个字节的数据就可以确定48个黑白点,48*48点阵汉字数据的前6个字节描述第一行的48个点,接着的6个字节描述第二行的48个点,依此类推,最后的6个字节描述第48行的48个点,如此构成48*48点阵的一个汉字,所以一个48*48点阵的汉字需要288个字节的数据。如果是一个16*16点阵的汉字,就可以用2个字节描述一行16个点,接下来的2个字节描述下一行的16个点,依此类推,一个16*16点阵汉字需要32个字节数据就够了。所以16*16点阵汉字库要比48*48点阵汉字库小得多。 国标汉字编码表(GB2312-80)是一个二维表,有94行94列,最多可容纳94*94=8836个汉字或符号,而实际上则包含6763个汉字,另外还有一些符号,其余都是空位。对编码表的行和列进行编码可以得到区位码,就是把汉字在编码表上对应的区号和位号合起来得到的四位数字编码,表中的行为区,区号在前,表中的列为位,位号在后,比如“啊”字的区位码是1601,即16区01位,(前15区是符号)。 UCDOS中fnt子目录中的“hzk48s“文件,就是48*48点阵的宋体汉字库,它占据1904K字节。包括了国标区位码中94个区,每区94个位的所有汉字,汉字库是按照先区后位顺序存储汉字的。先存第一区的94个汉字,再存第二区的94个汉字,依此类推,参见区位码表。所以48*48点阵汉字库的结构是,先是第一区的第一位的288个字节,然后是第一区的第二位的288个字节。如此,最后是87区的第94个汉字的288个字节。 2.如何获取汉字的点阵信息 获得48*48点阵信息的方法是:比如要得到“啊”字的48*48=288个字节的点阵信息,1)首先要知道“啊”字的机内码,这里还是先介绍一下机内码的概念,机内码是使用编码表的二进制值编码,由2个字节的代码组成。行为第一字节,列为第二字节,第一、二字节的最高位均设置为1,例如“啊”字编码表中行、列对应的二进制值1011000010100001,转换为十六进制数得B0A1,此为“啊”的机内码。机内码可以通过VB编程得到:zf$ =“啊” ,zf1 =Hex(Asc(zf$)),此时zf1=B0A1就是“啊”的机内码的十六进制数,参见程序8~9行。 2)然后要得到“啊”字的区位码。“啊”字所在的区和位的位置,可以通过查区位码表得到,也可以通过区位码和机内码的转换公式得到。区位码和机内码的十进制数转换公式是:Q(区码)=机内码第一个字节-160,W(位码)=机内码第二个字节-160。通过对上述公式进行编程可以得到区码q$= "&H" & Left(zf1, 2) ,q = Val(q$) –160,位码w$ = "&h" & Right(zf1, 2) ,w = Val(w$) –160,此时q=16,w=01,“啊”字的区位码是1601。参见程序10~13行。
3)有了区位码,下面的问题就是如何通过区位码找到“啊”字的点阵信息,上面说到汉字的点阵信息在汉字库中是按照区、位存储的,每个48*48点阵的汉字占288个字节,那么,某个汉字的点阵数据与该汉字的区、位码必须存在一定的对应关系,这个对应关系是:m = ((q - 1) * 94 + w - 1411) *288,其中m就是我们要找的该汉字的288个字节点阵数据的起始位置,q是区号,w是位号。利用这个公式,通过VB编程,(参见14行程序)可以很容易的读取ucdos中汉字库二进制文件中的“啊”字的48*48点阵数据如下:0000000000000000000000000000000000000000000000000003810000C00003838001E01823FFFFFFF01C73870007001FFB870007001C73860007001C738E0007001C738C0007001C738C0007001C73880007001C73986087001C739071C7001C73907FE7001C73B071C7001C73A071C7001C73A071C7001C739071C7001C739871C7001C738871C7001C738C71C7001C738C71C7001C738671C7001C738671C7001C738671C7001C738771C7001C73877FC7001FF38771C7001C738771C7001C738E71C7001C63FE6007001C039C0007001C03880007001C03800007001C038000070000038000070000038000070000038000070000038000070000038001FF00000380003F00000380001E00000380000C00000000000000000000000000。
3.如何验证所得到的数据就是“啊”字的48*48点阵数据呢?一是可以在纸上画出48条行线和48条列线,在行列的交叉点上描点的方法,先描第一行的6个字节6*8=48个点,接着再描第二行的48个点,依此类推,描完48行就能看出这个汉字的模样了,这种方法太麻烦,下面介绍一种用计算机描点的方法:首先取一个字节的点阵数据,然后把该数据的每一位分离出来,分离的方法就是把十进制数转换为二进制数的方法,即“除二取余”,被转换的数被2去除,如果能够整除则取0,不能被整除则取1,参见程序36~44行。然后根据扫描数据的每一位判断是0还是1,是1就在屏幕上画一个红点,是0就在屏幕上以背景色画一个不可见的点,参见程序45~53行。
4.编程方法:利用VisualBASIC5.0进行编程调用汉字库点阵信息非常方便。程序1~6行是设置全局变量,7~33是命令按钮的事件过程,其中8~14行的作用前面已经叙述,15~20行是读取数据文件。21~22行的作用是对数据进行处理,23行是把数据显示在文本框中。24~33行是为了描点而设置x和y坐标。35~54行是在图片框中把汉字画出来的子程序,前面已经说明。Form表单上放置text和picture控件和一个命令按钮。属性采用默认值。
5.程序清单如下:
1. Dim aAs Byte 2. Dimb 3. Public c 4. Dimpx 5. Dimpy 6. Dim kAs Integer 7. Private Sub Command1_Click() 8. zf$ ="啊" 9. zf1 =Hex(Asc(zf$)) 10. q$ ="&H" & Left(zf1, 2) 11. w$ ="&h" & Right(zf1, 2) 12. q =Val(q$) - 160 13. w =Val(w$) - 160 14. m =((q - 1) * 94 + w - 1411) * 288 15. Open"d:\ucdos\fnt\hzk48s" For Binary As #1 16. py =0: px = 0 17. For i= 1 To 288 18. m = m+ 1 19. Seek#1, m 20. Get#1, m, a 21. b =Hex(a) 22. IfMid$(b, 2, 2) <= "&0f" Then b = "0" & b 23. Text1.Text = Text1.Text + b + Chr(10) 24. b =a 25. Callhuahanzi 26. If i/ 6 <> Int(i / 6) Then 27. px =px + 8 28. Else 29. py =py + 1 30. px =0 31. EndIf 32. Nexti 33. Close 34. EndSub 35. Public Sub huahanzi() 36. For k= 1 To 8 37. c = b/ 2 38. If b/ 2 = Int(b / 2) Then 39. s = 0& s 40. Else 41. s = 1& s 42. EndIf 43. b =Int(c) 44. Nextk 45. ForL= 1 To 8 46. Picture1.DrawWidth = 1 47. Picture1.ScaleMode = 3 48. IfMid$(s, L, 1) = "1" Then 49. Picture1.PSet (px + L, py), QBColor(12) 50. Else 51. Picture1.PSet (px + L, py), BackColor 52. EndIf 53. NextL
54. EndSub
|