漢字編碼與漢字顯示


一、漢字區位碼、國標碼和機內碼

1、區位碼

  為了使每一個漢字有一個全國統一的代碼,1980年,我國頒布了第一個漢字編碼的國家標准: GB2312-80《信息交換用漢字編碼字符集》基本集,這個字符集是我國中文信息處理技術的發展基礎,也是目前國內所有漢字系統的統一標准。

   所有的國標漢字與符號組成一個94×94的矩陣。在此方陣中,每一行稱為一個"區",每一列稱為一個"位",因此,這個方陣實際上組成了一個有94個區(區號分別為0 1到94)、每個區內有94個位(位號分別為01到94)的漢字字符集。一個漢字所在的區號和位號簡單地組合在一起就構成了該漢字的"區位碼"。在漢字的區位碼中,高兩位為區號,低兩位為位號。

  在區位碼中,01-09區為682個特殊字符,16~87區為漢字區,包含6763個漢字 。其中16-55區為一級漢字(3755個最常用的漢字,按拼音字母的次序排列),56-87區為二級漢字(3008個漢字,按部首次序排列)。

    需要注意的是:區位碼通常都是用十進制表示的,例如“誠”字的區位碼為1947,也就說它位於19區第47個字符。

                                 摘自:《漢字區位碼

  2、國標碼

國家標准代碼,簡稱國標碼,是中華人民共和國的中文常用漢字編碼集。國家標准強制標准冠以“GB”。

現時中華人民共和國官方強制使用GB 18030標准,但較舊的計算機仍然使用GB 2312。
 
國標碼 = 區位碼(16進制化--區碼和位碼分別進行16進制轉化)+2020H

3、機內碼

  計算機只識別由0、1組成的代碼,ASCII碼是英文信息處理的標准編碼,漢字信息處理也必須有一個統一的標准編碼。 漢字交換碼(國標碼)主要用於漢字信息交換,我國國家標准局於1981年5月頒布了《信息交換用漢字編碼字符集——基本集》,代號為GB2312-80,共對6763個漢字和682個圖形字符進行了編碼。

  其編碼原則為:漢字用兩個字節表示,原則上,兩個字節可以表示 256×256=65536 種不同的符號,作為漢字編碼表示的基礎是可行的。但考慮到漢字編碼與其它國際通用編碼,如ASCII 西文字符編碼的關系,我國國家標准局采用了加以修正的兩字節漢字編碼方案,只用了兩個字節的低7位。這個方案可以容納128×128=16384 種不同的漢字,但為了與標准ASCII碼兼容,每個字節中都不能再用32個控制功能碼和碼值為32的空格以及127的操作碼。所以每個字節只能有94個編碼。這樣,雙七位實際能夠表示的字數是:94×94=8836個。

機內碼 = 國標碼 + 8080H
機內碼 = 區位碼(16進制化--區碼和位碼分別進行16進制轉化) + a0a0H

                                   摘自:《機內碼

4、相互轉換

  • 內碼轉換為區位碼

         區位碼:   區碼=內碼高字節-0xa0

                       位碼=內碼低字節-0xa0

         例如:“國”內碼為:0xb9,0xfa

       16進制表示的區位碼:0x19,0x5a

                  其區位碼(默認為10進制):2590

  • 區位碼轉換為內碼

        內碼:  內碼高字節=區碼+0xa0

                  內碼低字節=位碼+0xa0

         例如:“海”區位碼為:2603

       16進制表示的區位碼:0x1a,0x03

           其內碼(默認為16進制):0xba,0xa3

二、字模

  漢字在顯示的時候,是以點陣的形式顯示出來的,常見到的有16*16點陣、24*24點陣、32*32點陣。比如說“啊”的16*16點陣字模如下,共256Bits,占用32 Bytes:

0x00,0x00,0xf7,0x7e,0x95,0x04,0x95,0x04,0x96,0x74,0x96,0x54,0x95,0x54,0x95,0x54,
0x95,0x54,0xf5,0x54,0x97,0x74,0x04,0x04,0x04,0x04,0x05,0x04,0x04,0x14,0x04,0x08

  字模顯示的時候,以兩個字節表示一行像素點,16行就構成了一個完整的字模。屏幕在顯示的時候,1顯示為亮色,0顯示為背景色,這樣就能把字體顯示出來。用C測試程序,把1的地方顯示為“*”,0的地方顯示為空,效果如下:

三、字庫

  字庫,就是所有漢字字模的集合。顯然,在編排這些字模的時候需要一定的順序(規則),而這個規則就是“機內碼”。根據機內碼的漢字布局,將對應的漢字字模進行整合,形成字庫文件。在使用的時候,應用程序根據漢字的機內碼,從字庫中找到對應的存儲位置,取出字模,進行顯示。機內碼就是漢字在字庫中的索引。

  在區位碼中,01-09區為682個特殊字符,16~87區為漢字區,有效漢字6768個。在制作字庫的時候把特殊字符刪除,只使用有效漢字區。也就是說我們從第16區的第1位開始進行字模收集,當第16區收集結束,緊接着收集第17區,直到第87區編排結束。總共收集6768個漢字,占用空間216576 Bytes。

☆ 機內碼與字庫偏移量的關系

  偏移量 = ((機內碼高字節-0xb0)*94+機內碼低字節-0xa1)*32

四、測試程序

#include <stdio.h>

void ShowOneWord(const char *str);
int GetGBKCode(unsigned char* pBuffer,const char * c);
void ShowWords(const char *str);

/**
  * @brief  main function
  * @param  Nove
  * @retval Nove
  */
int main(void){
    ShowWords("測試漢字顯示");
    return 0;
}

/**
  * @brief  Show  multiple Chinese Words
  * @param  str       : point to Chinese location code
  * @retval Nove
  */
void ShowWords(const char *str){
    if(NULL == str)    return;
    while(*str != 0){
        ShowOneWord(str);
        str += 2;
    }
}

/**
  * @brief  Show one Chinese Word
  * @param  str       : point to Chinese location code
  * @retval Nove
  */
void ShowOneWord(const char *str){
    unsigned char buffer[32];
    int i,j;
    unsigned char k;

    GetGBKCode(buffer,str);
    for(i=0;i<16;i++){
        for(j=0;j<8;j++){
            k = buffer[2*i] << j;
            if(k & 0x80){
                printf("*");
            }
            else{
                printf(" ");
            }
        }
        for(j=0;j<8;j++){
            k = buffer[2*i+1] << j;
            if(k & 0x80){
                printf("*");
            }
            else{
                printf(" ");
            }
        }
        printf("\n");
    }
    printf("\n\n");
}

/**
  * @brief  Get type matrix from HZLIB.bin based on Chinese location code
  * @param  pBuffer: point to 32 bytes type matrix buffer
  *         c       : point to Chinese location code
  * @retval 0(success)  -1(fail)
  */
int GetGBKCode(unsigned char* pBuffer,const char * c){
    unsigned char High8bit,Low8bit;
    unsigned int pos;
    FILE * fp;

    High8bit=*c;
    Low8bit=*(c+1);

    pos = ((High8bit-0xa0-16)*94+Low8bit-0xa0-1)*2*16;
                                        //get type matrix location

    fp =fopen("HZLIB.bin","r");            //open type matrix file

    if (fp != NULL)
    {
        fseek (fp,pos,SEEK_SET);        //set read start point
        fread(pBuffer,1,32,fp);            //read 32 bytes
        fclose(fp);
        return 0;
    }
    else
        return -1;
}
View Code

五、注意

1、漢字在程序中是以機內碼進行表示,英文字符則是ASCII,漢字的機內碼占兩個字節

2、漢字表示的時候,以雙引號括起來代表一個字符串,只有一個漢字的字符串,實際占用3個字節的存儲空間。

 

附eclipse測試代碼: Chinese_Test.zip

參考資料:《STM32庫開發實戰指南》

      GB2312簡體中文編碼表


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM