HZK16漢字16*16點陣字庫的使用及示例程序


最近(很久之前的最近)在弄硬件,買了一塊彩屏,需要字庫,所以就把很久以前會的知識拿出來溫習了一遍。果然好多都記憶模糊了。網上的代碼我看過,很多都有問題,這里我帖出來的是我自己寫的代碼,沒有問題。

HZK16字庫是符合GB2312標准的16×16點陣字庫,HZK16的GB2312-80支持的漢字有6763個,符號682個。其中一級漢字有 3755個,按聲序排列,二級漢字有3008個,按偏旁部首排列。

我們在一些應用場合根本用不到這么多漢字字模,所以在應用時就可以只提取部分字體作為己用。

HZK16字庫里的16×16漢字一共需要256個點來顯示,也就是說需要32個字節才能達到顯示一個普通漢字的目的。

我們知道一個GB2312漢字是由兩個字節編碼的,范圍為0xA1A1~0xFEFEA1-A9為符號區,B0-F7為漢字區。每一個區有94個字符(注意:這只是編碼的許可范圍,不一定都有字型對應,比如符號區就有很多編碼空白區域)。

下面以漢字"我"為例,介紹如何在HZK16文件中找到它對應的32個字節的字模數據。前面說到一個漢字占兩個字節,這兩個中前一個字節為該漢字的區號,后一個字節為該字的位號。其中,每個區記錄94個漢字,位號為該字在該區中的位置。所以要找到"我"在hzk16庫中的位置就必須得到它的區碼和位碼。

區碼:漢字的第一個字節-0xA0 (因為漢字編碼是從0xA0區開始的, 所以文件最前面就是從0xA0區開始, 要算出相對區碼)
位碼:漢字的第二個字節-0xA0

這樣我們就可以得到漢字在HZK16中的絕對偏移位置:

offset=(94*(區碼-1)+(位碼-1))*32

注解:

  • 區碼減1是因為數組是以0為開始而區號位號是以1為開始的
  • (94*(區號-1)+位號-1)是一個漢字字模占用的字節數
  • 最后乘以32是因為漢字庫文應從該位置起的32字節信息記錄該字的字模信息(前面提到一個漢字要有32個字節顯示)

我畫的圖示:

●●●●●●●●●●●●●●●●   →   0x04,0x80
●●●●●●●●●●●●●●●●   →   0x0E,0xA0
●●●●●●●●●●●●●●●●   →   0x78,0x90
●●●●●●●●●●●●●●●●   →   0x08,0x90
●●●●●●●●●●●●●●●●   →   0x08,0x84
●●●●●●●●●●●●●●●●   →   0xFF,0xFE
●●●●●●●●●●●●●●●●   →   0x08,0x80
●●●●●●●●●●●●●●●●   →   0x08,0x90
●●●●●●●●●●●●●●●●   →   0x0A,0x90
●●●●●●●●●●●●●●●●   →   0x0C,0x60
●●●●●●●●●●●●●●●●   →   0x18,0x40
●●●●●●●●●●●●●●●●   →   0x68,0xA0
●●●●●●●●●●●●●●●●   →   0x09,0x20
●●●●●●●●●●●●●●●●   →   0x0A,0x14
●●●●●●●●●●●●●●●●   →   0x28,0x14
●●●●●●●●●●●●●●●●   →   0x10,0x0C

所以,'我'在HZK16 16*16點陣字庫的存放的序列為:
(一行一行地保存,共16行,每行2個字節, 共32個字節)

04 80 0E A0 78 90 08 90 08 84 FF FE 08 80 08 90
0A 90 0C 60 18 40 68 A0 09 20 0A 14 28 14 10 0C

就像下面這樣:

以下是我自己寫的示例程序, 可以自己修改成其它的數據格式.(很簡單, 所以沒寫注釋)。

示例源代碼

版本1

#include <stdio.h> int main(void) { FILE* fphzk = NULL; int i, j, k, offset; int flag; unsigned char buffer[32]; unsigned char word[3] = "我"; unsigned char key[8] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; fphzk = fopen("hzk16", "rb"); if(fphzk == NULL){ fprintf(stderr, "error hzk16\n"); return 1; } offset = (94*(unsigned int)(word[0]-0xa0-1)+(word[1]-0xa0-1))*32; fseek(fphzk, offset, SEEK_SET); fread(buffer, 1, 32, fphzk); for(k=0; k<32; k++){ printf("%02X ", buffer[k]); } for(k=0; k<16; k++){ for(j=0; j<2; j++){ for(i=0; i<8; i++){ flag = buffer[k*2+j]&key[i]; printf("%s", flag?"●":"○"); } } printf("\n"); } fclose(fphzk); fphzk = NULL; return 0; }

版本2

#include <stdio.h> #include <stdlib.h> int main(void) { FILE* fphzk = NULL; int i, j, k, offset; int flag; unsigned char buffer[32]; unsigned char word[5]; unsigned char key[8] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; fphzk = fopen("hzk16", "rb"); if(fphzk == NULL){ fprintf(stderr, "error hzk16\n"); return 1; } while(1){ printf("輸入要生成字模的漢字(多個):"); for(;;){ fgets((char*)word, 3, stdin); if(*word == '\n') break; offset = (94*(unsigned int)(word[0]-0xa0-1)+(word[1]-0xa0-1))*32; fseek(fphzk, offset, SEEK_SET); fread(buffer, 1, 32, fphzk); for(k=0; k<16; k++){ for(j=0; j<2; j++){ for(i=0; i<8; i++){ flag = buffer[k*2+j]&key[i]; printf("%s", flag?"●":"○"); } } printf("\n"); } printf("uchar code key[32] = {"); for(k=0; k<31; k++){ printf("0x%02X,", buffer[k]); } printf("0x%02X};\n", buffer[31]); printf("\n"); } } fclose(fphzk); fphzk = NULL; return 0; }

 轉自:https://blog.twofei.com/embedded/hzk.html


免責聲明!

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



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