摘要:本文敘述了漢字庫的結(jié)構(gòu)及漢字點(diǎn)陣信息的獲得方法,并用VisualBasic5.0進(jìn)行編程,調(diào)用UCDOS中48*48(48行乘48列)點(diǎn)陣的漢字庫,獲取漢字點(diǎn)陣數(shù)據(jù),顯示在文本框中,同時(shí)在圖片框中用畫點(diǎn)的方法把該漢字畫出來。這是15年前自己寫的一篇論文,好像還有參考價(jià)值,特收錄在此。
1.48*48點(diǎn)陣漢字庫的結(jié)構(gòu) 大家在計(jì)算機(jī)屏幕上看到的漢字是由一系列的點(diǎn)構(gòu)成的,如果用針式打印機(jī)把漢字打印在紙上,可以更清楚地看出是由一組黑點(diǎn)組成,這組黑點(diǎn)可能是24*24的點(diǎn)陣,如果是16*16的點(diǎn)陣看得就更清楚,如果是48*48點(diǎn)陣,因?yàn)閱挝幻娣e的點(diǎn)數(shù)增加,就看不出是由點(diǎn)組成的漢字了。計(jì)算機(jī)在顯示或打印漢字時(shí)要調(diào)用漢字庫。 因?yàn)槊總(gè)字節(jié)(8位的二進(jìn)制數(shù))數(shù)據(jù)可以描述8個(gè)點(diǎn),(1代表黑,0代表白),所以用6個(gè)字節(jié)的數(shù)據(jù)就可以確定48個(gè)黑白點(diǎn),48*48點(diǎn)陣漢字?jǐn)?shù)據(jù)的前6個(gè)字節(jié)描述第一行的48個(gè)點(diǎn),接著的6個(gè)字節(jié)描述第二行的48個(gè)點(diǎn),依此類推,最后的6個(gè)字節(jié)描述第48行的48個(gè)點(diǎn),如此構(gòu)成48*48點(diǎn)陣的一個(gè)漢字,所以一個(gè)48*48點(diǎn)陣的漢字需要288個(gè)字節(jié)的數(shù)據(jù)。如果是一個(gè)16*16點(diǎn)陣的漢字,就可以用2個(gè)字節(jié)描述一行16個(gè)點(diǎn),接下來的2個(gè)字節(jié)描述下一行的16個(gè)點(diǎn),依此類推,一個(gè)16*16點(diǎn)陣漢字需要32個(gè)字節(jié)數(shù)據(jù)就夠了。所以16*16點(diǎn)陣漢字庫要比48*48點(diǎn)陣漢字庫小得多。 國標(biāo)漢字編碼表(GB2312-80)是一個(gè)二維表,有94行94列,最多可容納94*94=8836個(gè)漢字或符號,而實(shí)際上則包含6763個(gè)漢字,另外還有一些符號,其余都是空位。對編碼表的行和列進(jìn)行編碼可以得到區(qū)位碼,就是把漢字在編碼表上對應(yīng)的區(qū)號和位號合起來得到的四位數(shù)字編碼,表中的行為區(qū),區(qū)號在前,表中的列為位,位號在后,比如“啊”字的區(qū)位碼是1601,即16區(qū)01位,(前15區(qū)是符號)。 UCDOS中fnt子目錄中的“hzk48s“文件,就是48*48點(diǎn)陣的宋體漢字庫,它占據(jù)1904K字節(jié)。包括了國標(biāo)區(qū)位碼中94個(gè)區(qū),每區(qū)94個(gè)位的所有漢字,漢字庫是按照先區(qū)后位順序存儲(chǔ)漢字的。先存第一區(qū)的94個(gè)漢字,再存第二區(qū)的94個(gè)漢字,依此類推,參見區(qū)位碼表。所以48*48點(diǎn)陣漢字庫的結(jié)構(gòu)是,先是第一區(qū)的第一位的288個(gè)字節(jié),然后是第一區(qū)的第二位的288個(gè)字節(jié)。如此,最后是87區(qū)的第94個(gè)漢字的288個(gè)字節(jié)。 2.如何獲取漢字的點(diǎn)陣信息 獲得48*48點(diǎn)陣信息的方法是:比如要得到“啊”字的48*48=288個(gè)字節(jié)的點(diǎn)陣信息,1)首先要知道“啊”字的機(jī)內(nèi)碼,這里還是先介紹一下機(jī)內(nèi)碼的概念,機(jī)內(nèi)碼是使用編碼表的二進(jìn)制值編碼,由2個(gè)字節(jié)的代碼組成。行為第一字節(jié),列為第二字節(jié),第一、二字節(jié)的最高位均設(shè)置為1,例如“啊”字編碼表中行、列對應(yīng)的二進(jìn)制值1011000010100001,轉(zhuǎn)換為十六進(jìn)制數(shù)得B0A1,此為“啊”的機(jī)內(nèi)碼。機(jī)內(nèi)碼可以通過VB編程得到:zf$ =“啊” ,zf1 =Hex(Asc(zf$)),此時(shí)zf1=B0A1就是“啊”的機(jī)內(nèi)碼的十六進(jìn)制數(shù),參見程序8~9行。 2)然后要得到“啊”字的區(qū)位碼。“啊”字所在的區(qū)和位的位置,可以通過查區(qū)位碼表得到,也可以通過區(qū)位碼和機(jī)內(nèi)碼的轉(zhuǎn)換公式得到。區(qū)位碼和機(jī)內(nèi)碼的十進(jìn)制數(shù)轉(zhuǎn)換公式是:Q(區(qū)碼)=機(jī)內(nèi)碼第一個(gè)字節(jié)-160,W(位碼)=機(jī)內(nèi)碼第二個(gè)字節(jié)-160。通過對上述公式進(jìn)行編程可以得到區(qū)碼q$= "&H" & Left(zf1, 2) ,q = Val(q$) –160,位碼w$ = "&h" & Right(zf1, 2) ,w = Val(w$) –160,此時(shí)q=16,w=01,“啊”字的區(qū)位碼是1601。參見程序10~13行。
3)有了區(qū)位碼,下面的問題就是如何通過區(qū)位碼找到“啊”字的點(diǎn)陣信息,上面說到漢字的點(diǎn)陣信息在漢字庫中是按照區(qū)、位存儲(chǔ)的,每個(gè)48*48點(diǎn)陣的漢字占288個(gè)字節(jié),那么,某個(gè)漢字的點(diǎn)陣數(shù)據(jù)與該漢字的區(qū)、位碼必須存在一定的對應(yīng)關(guān)系,這個(gè)對應(yīng)關(guān)系是:m = ((q - 1) * 94 + w - 1411) *288,其中m就是我們要找的該漢字的288個(gè)字節(jié)點(diǎn)陣數(shù)據(jù)的起始位置,q是區(qū)號,w是位號。利用這個(gè)公式,通過VB編程,(參見14行程序)可以很容易的讀取ucdos中漢字庫二進(jìn)制文件中的“啊”字的48*48點(diǎn)陣數(shù)據(jù)如下:0000000000000000000000000000000000000000000000000003810000C00003838001E01823FFFFFFF01C73870007001FFB870007001C73860007001C738E0007001C738C0007001C738C0007001C73880007001C73986087001C739071C7001C73907FE7001C73B071C7001C73A071C7001C73A071C7001C739071C7001C739871C7001C738871C7001C738C71C7001C738C71C7001C738671C7001C738671C7001C738671C7001C738771C7001C73877FC7001FF38771C7001C738771C7001C738E71C7001C63FE6007001C039C0007001C03880007001C03800007001C038000070000038000070000038000070000038000070000038000070000038001FF00000380003F00000380001E00000380000C00000000000000000000000000。
3.如何驗(yàn)證所得到的數(shù)據(jù)就是“啊”字的48*48點(diǎn)陣數(shù)據(jù)呢?一是可以在紙上畫出48條行線和48條列線,在行列的交叉點(diǎn)上描點(diǎn)的方法,先描第一行的6個(gè)字節(jié)6*8=48個(gè)點(diǎn),接著再描第二行的48個(gè)點(diǎn),依此類推,描完48行就能看出這個(gè)漢字的模樣了,這種方法太麻煩,下面介紹一種用計(jì)算機(jī)描點(diǎn)的方法:首先取一個(gè)字節(jié)的點(diǎn)陣數(shù)據(jù),然后把該數(shù)據(jù)的每一位分離出來,分離的方法就是把十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)的方法,即“除二取余”,被轉(zhuǎn)換的數(shù)被2去除,如果能夠整除則取0,不能被整除則取1,參見程序36~44行。然后根據(jù)掃描數(shù)據(jù)的每一位判斷是0還是1,是1就在屏幕上畫一個(gè)紅點(diǎn),是0就在屏幕上以背景色畫一個(gè)不可見的點(diǎn),參見程序45~53行。
4.編程方法:利用VisualBASIC5.0進(jìn)行編程調(diào)用漢字庫點(diǎn)陣信息非常方便。程序1~6行是設(shè)置全局變量,7~33是命令按鈕的事件過程,其中8~14行的作用前面已經(jīng)敘述,15~20行是讀取數(shù)據(jù)文件。21~22行的作用是對數(shù)據(jù)進(jìn)行處理,23行是把數(shù)據(jù)顯示在文本框中。24~33行是為了描點(diǎn)而設(shè)置x和y坐標(biāo)。35~54行是在圖片框中把漢字畫出來的子程序,前面已經(jīng)說明。Form表單上放置text和picture控件和一個(gè)命令按鈕。屬性采用默認(rèn)值。
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
|