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

前言:最近有個關於泰國文字識別並打印的項目。之前對泰文的瞭解只聽過“薩瓦迪卡”-_-!!,所以前兩天在學習泰文的排版規範及unicode編碼,瞭解之後開始學習文字點陣打印的原理及代碼編寫。今天學習了漢字16*16點陣字庫的使用。

這裏首先感謝陪她去流浪大佬的文章(這個大佬的id一聽就是有女朋友的,羨慕o.o),文章簡介明瞭、通俗易懂,代碼講解也非常的詳細。

原理:

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個字節顯示)

圖示:

“我”的點陣輸出如下圖所示:
在這裏插入圖片描述

所以,“我”在HZK16*16點陣字庫的存放序列爲(一行一行地保存,共16行,每行2個字節,共32個字節):
在這裏插入圖片描述
程序輸出應該這樣:
在這裏插入圖片描述

源代碼實例:

版本1

#include <stdio.h>

int main(void)
{
	FILE* fd = 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 };

	fd = fopen("hzk16", "rb");
	if (fd == NULL)
	{
		fprintf(stderr, "error hzk16\n");
		return 1;
	}

	offset = (94 * (unsigned int)(word[0] - 0xa0 - 1) + (word[1] - 0xa0 - 1)) * 32;
	fseek(fd, offset, SEEK_SET);
	fread(buffer, 1, 32, fd);
	for (k = 0; k<32; k++){
		printf("%02X ", buffer[k]);
	}
	printf("\n");
	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(fd);
	fd = 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;
}

版本3

#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[2] = {0xCE, 0xD2}; // 改成你的轉碼後的漢字編碼
    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<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");
    }

    for(k=0; k<31; k++){
        printf("0x%02X,", buffer[k]);
    }

    printf("\n");

    fclose(fphzk);
    fphzk = NULL;
    return 0;
}

各種字庫下載地址:http://pan.baidu.com/share/link?shareid=2514580636&uk=320828865

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章