國(guó)家標(biāo)準(zhǔn)漢字字符集GB2312-80共收集了共7445個(gè)漢字和圖形符號(hào),其中漢字6763個(gè),分為二級(jí),
一級(jí)漢字3755個(gè),二級(jí)漢字3008個(gè)。漢字圖形符號(hào)根據(jù)其位置將其分為94個(gè)“區(qū)”,
每個(gè)區(qū)包含94個(gè)漢字字符,每個(gè)漢字字符又稱為一個(gè)“位”。區(qū)的序號(hào)和位的序號(hào)都是從01到94,
UCDOS軟件中的文件HZK16和文件ASC16分別為16×16的國(guó)標(biāo)漢字點(diǎn)陣文件和8×16的ASCII碼點(diǎn)陣文件,
以二進(jìn)制格式存儲(chǔ)。在文件HZK16中,按漢字區(qū)位碼從小到大依次存有國(guó)標(biāo)區(qū)位碼表中的所有漢字,
每個(gè)漢字占用32個(gè)字節(jié),每個(gè)區(qū)為94個(gè)漢字。在文件ASC16中按ASCII碼從小到大依次存有
8×16的ASCII碼點(diǎn)陣,每個(gè)ASCII碼占用16個(gè)字節(jié)。
國(guó)家標(biāo)準(zhǔn)漢字字符集GB2312-80共收集了共7445個(gè)漢字和圖形符號(hào),其中漢字6763個(gè),分為二級(jí),
一級(jí)漢字3755個(gè),二級(jí)漢字3008個(gè)。漢字圖形符號(hào)根據(jù)其位置將其分為94個(gè)“區(qū)”,
每個(gè)區(qū)包含94個(gè)漢字字符,每個(gè)漢字字符又稱為一個(gè)“位”。區(qū)的序號(hào)和位的序號(hào)都是從01到94,
UCDOS軟件中的文件HZK16和文件ASC16分別為16×16的國(guó)標(biāo)漢字點(diǎn)陣文件和8×16的ASCII碼點(diǎn)陣文件,
以二進(jìn)制格式存儲(chǔ)。在文件HZK16中,按漢字區(qū)位碼從小到大依次存有國(guó)標(biāo)區(qū)位碼表中的所有漢字,
每個(gè)漢字占用32個(gè)字節(jié),每個(gè)區(qū)為94個(gè)漢字。在文件ASC16中按ASCII碼從小到大依次存有
8×16的ASCII碼點(diǎn)陣,每個(gè)ASCII碼占用16個(gè)字節(jié)。
在PC機(jī)的文本文件中,漢字是以機(jī)內(nèi)碼的形式存儲(chǔ)的,每個(gè)漢字占用兩個(gè)字節(jié):第一個(gè)字節(jié)為區(qū)碼,
為了與ASCII碼區(qū)別,范圍從十六進(jìn)制的0A1H開(kāi)始(小于80H的為ASCII碼字符),
對(duì)應(yīng)區(qū)位碼中區(qū)碼的第一區(qū);第二個(gè)字節(jié)為位碼,范圍也是從0A1H開(kāi)始,對(duì)應(yīng)某區(qū)中的第一個(gè)位碼。
這樣,將漢字機(jī)內(nèi)碼減去0A0AH就得該漢字的區(qū)位碼。
例如漢字“房”的機(jī)內(nèi)碼為十六進(jìn)制的“B7BF”,其中“B7”表示區(qū)碼,“BF”表示位碼。
所以“房”的區(qū)位碼為0B7BFH-0A0A0H=171FH。將區(qū)碼和位碼分別轉(zhuǎn)換為十進(jìn)制得漢字“房”的
區(qū)位碼為“2331”,即“房”的點(diǎn)陣位于第23區(qū)的第31個(gè)字的位置,相當(dāng)于在文件HZK16中的
位置為第32×[(23-1) ×94+(31-1)]=67136B以后的32個(gè)字節(jié)為“房”的顯示點(diǎn)陣。
ASCII碼的顯示與漢字的顯示原理相同,在ASC16文件中不存在機(jī)內(nèi)碼的問(wèn)題,
其顯示點(diǎn)陣直接按ASCII碼從小到大依次排列,不過(guò)每個(gè)ASCII碼在文本中只占1個(gè)字節(jié)并且小于80h,
每個(gè)ASCII碼為8X16點(diǎn)陣,即在ASCII16文件中,每個(gè)ASCII碼的點(diǎn)陣也只占16個(gè)字節(jié)。
以下是讀取hzk16的C部分語(yǔ)言代碼(僅供參考):
void dis_cc(unsigned int x,unsigned int y,unsigned int color,unsigned int codeh,
unsigned int codel,unsigned int circle,unsigned int kind,unsigned int mode)
{
char word[32];
int area,bit;
long count,offset;
unsigned long count,offset;
unsigned int i,j;
area = (codeh&0x00ff)-0xa0-1; //根據(jù)機(jī)內(nèi)碼取得區(qū)碼
bit = (codel&0x00ff)-0xa0-1; //根據(jù)機(jī)內(nèi)碼取得位碼
offset = area*94+bit; //取得偏移量
count = 32l*(long)offset;
lseek(HZK16,count,SEEK_SET);//在HZK16文件中找到點(diǎn)陣起始位置
j=_read(HZK16,&word[0],32);//讀取32字節(jié)的點(diǎn)陣信息
在電腦中,所有的數(shù)據(jù)都是以0和1保存的,按不同的數(shù)據(jù)操作,可以得到不同的結(jié)果。對(duì)于顯示英文操作,由于英文字母種類很少,只需要8位(一字節(jié))
即可。而對(duì)于中文,常用卻有6000以上,于是我們的DOS前輩想了一個(gè)辦法,就是將
ASCII表的高128個(gè)很少用到的數(shù)值以兩個(gè)為一組來(lái)表示漢字,即漢字的內(nèi)碼。而剩下的低128位則留給英文字符使用,即英文的內(nèi)碼。 漢字字模
得到了漢字的內(nèi)碼后,還僅是一組數(shù)字,那又如何在屏幕上去顯示呢?這就涉及到文字的字模,字模雖然也是一組數(shù)字,但它的意義卻與數(shù)字的意義有了根本的變化,它是用數(shù)字的各位信息來(lái)記載英文或漢字的形狀,如英文的‘A‘在字模中是這樣記載的:
漢字內(nèi)碼
在電腦中,所有的數(shù)據(jù)都是以0和1保存的,按不同的數(shù)據(jù)操作,可以得到不同的結(jié)果。對(duì)于顯示英文操作,由于英文字母種類很少,只需要8位(一字節(jié))即
可。而對(duì)于中文,常用卻有6000以上,于是我們的DOS前輩想了一個(gè)辦法,就是將
ASCII表的高128個(gè)很少用到的數(shù)值以兩個(gè)為一組來(lái)表示漢字,即漢字的內(nèi)碼。而剩下的低128位則留給英文字符使用,即英文的內(nèi)碼。 漢字字模
得到了漢字的內(nèi)碼后,還僅是一組數(shù)字,那又如何在屏幕上去顯示呢?這就涉及到文字的字模,字模雖然也是一組數(shù)字,但它的意義卻與數(shù)字的意義有了根本的變化,它是用數(shù)字的各位信息來(lái)記載英文或漢字的形狀,如英文的‘A‘在字模中是這樣記載的:
而中文的“你”在字模中卻是這樣記載的:
在硬件系統(tǒng)內(nèi),英文的字模信息一般固化在ROM里,中文的字模信息一般記錄在漢字庫(kù)文件HZK16里。
采用如何在點(diǎn)陣LED或LCD中顯示漢字?
假設(shè)你采用16x16點(diǎn)陣漢字,水平掃描。
顯示漢字為“模”,用產(chǎn)生如下字模
unsigned char mo[]={
0x00,0x00, 0x10,0x90, 0x10,0x94, 0x13,0xFE,
0x7C,0x90, 0x11,0xFC, 0x19,0x04, 0x35,0xFC,
0x35,0x04, 0x51,0xFC, 0x50,0x40, 0x17,0xFE,
0x10,0x90, 0x11,0x08, 0x16,0x06, 0x00,0x00
};
代碼如下:
unsigned char cmp_w[8]={128,64,32,16,8,4,2,1};
void FontDisplay(int x, int y, unsigned char * FontModule)
{
for(int row=0;row<16;row++)
{
for(int c=0;c<8;c++)
if((FontModule[row*2]&cmp_w[c])!=0)
putpixel(c+x,row+y,15);
for(c=0;c<8;c++)
if((FontModule[row*2+1]&cmp_w[c])!=0)
putpixel(c+8+x,row+y,15);
}
main(){
FontDisplay(5,10,mo);
}
24x24點(diǎn)陣代碼示例(水平掃描):
unsigned char mo[]={
0x00,0x00,0x00, 0x00,0x00,0x00, 0x07,0x0C,0xC0, 0x06,0x0C,0xC0,
0x06,0x0C,0xDC, 0x06,0x7F,0xF0, 0x06,0xCC,0xC0, 0x1F,0xF0,0x70,
0x06,0x3F,0xF0, 0x07,0x30,0x70, 0x0F,0xBF,0xF0, 0x0E,0xF0,0x70,
0x1E,0xF0,0x70, 0x1E,0x3F,0xF0, 0x36,0x06,0x18, 0x06,0xFF,0xFC,
0x06,0x07,0x00, 0x06,0x0F,0x80, 0x06,0x0C,0xE0, 0x06,0x38,0x7C,
0x06,0xE0,0x18, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00
};
unsigned char cmp_w[8]={128,64,32,16,8,4,2,1};
void FontDisplay(int x, int y, unsigned char * FontModule)
{
for(int row=0;row<24;row++)
{
for(int c=0;c<8;c++)
if((FontModule[row*3]&cmp_w[c])!=0)
putpixel(c+x,row+y,15);
for(c=0;c<8;c++)
if((FontModule[row*3+1]&cmp_w[c])!=0)
putpixel(c+8+x,row+y,15);
for(c=0;c<8;c++)
if((FontModule[row*3+2]&cmp_w[c])!=0)
putpixel(c+16+x,row+y,15);
}
}
main(){
FontDisplay(5,10,mo);
}
putpixel函數(shù):
putpixel(int x,int y,int color)
x,y為坐標(biāo),color為顏色值.該函數(shù)在(x,y)點(diǎn)設(shè)定象素的顏色.由于硬件的不同,也許提供的函數(shù)不同,用戶可把此函數(shù)作為參考,必要時(shí)用硬件提供的函數(shù)取而代之.
點(diǎn)陣字庫(kù)
一般我們使用16*16的點(diǎn)陣宋體字庫(kù),所謂16*16,是每一個(gè)漢字在縱、橫各16點(diǎn)的區(qū)域內(nèi)顯示的。
不過(guò)后來(lái)又有了HZK12、HZK24,HZK32和HZK48字庫(kù)及黑體、楷體和隸書(shū)字庫(kù)。
雖然漢字庫(kù)種類繁多,但都是按照區(qū)位的順序排列的。前一個(gè)字節(jié)為該漢字的區(qū)號(hào),后一個(gè)字節(jié)為該字的位號(hào)。
每一個(gè)區(qū)記錄94個(gè)漢字,位號(hào)則為該字在該區(qū)中的位置。
因此,漢字在漢字庫(kù)中的具體位置計(jì)算公式為:94*(區(qū)號(hào)-1)+位號(hào)-1。
減1是因?yàn)閿?shù)組是以0為開(kāi)始而區(qū)號(hào)位號(hào)是以1為開(kāi)始的。
這僅為以漢字為單位該漢字在漢字庫(kù)中的位置,那么,如何得到以字節(jié)為單位得到該漢字在漢字庫(kù)中的位置呢?
只需乘上一個(gè)漢字字模占用的字節(jié)數(shù)即可,
即:(94*(區(qū)號(hào)-1)+位號(hào)-1)*一個(gè)漢字字模占用字節(jié)數(shù),而按每種漢字庫(kù)的漢字大小不同又會(huì)得到不同的結(jié)果。
以16*16點(diǎn)陣字庫(kù)為例,計(jì)算公式則為:(94*(區(qū)號(hào)-1)+(位號(hào)-1))*32。
漢字庫(kù)文該從該位置起的32字節(jié)信息即記錄了該字的字模信息。
了解點(diǎn)陣漢字及漢字庫(kù)的構(gòu)成原理后,顯示漢字就變得簡(jiǎn)單。以16*16點(diǎn)陣字庫(kù)為例,
通常的方法是:將文件工作指針移到需要的漢字字模處、將漢字庫(kù)文件讀入一2*16數(shù)組再用for循環(huán)一位位地顯示。
#include "graphics.h"
#include "stdio.h"
main()
{ int i=VGA,j=VGAHI,k;
unsigned char mat[16][2],chinease[3]="我";
FILE *HZK;
if((HZK=fopen("hzk16","rb"))==NULL)exit(0);
initgraph(&i,&j,"");
i=chinease[0]-0xa0;j=chinease[1]-0xa0; /*獲得區(qū)碼與位碼*/
fseek(HZK,(94*(i-1)+(j-1))*32l,SEEK_SET);
fread(mat,32,1,HZK);
for(j=0;j<16;j++)
for(i=0;i<2;i++)
for(k=0;k<8;k++)
if(mat[j][i]&(0x80>>k)) /*測(cè)試為1的位則顯示*/
putpixel(i*8+k,j,WHITE);
getch();
closegraph();
fclose(HZK); (轉(zhuǎn))