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

  • 29
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 16x16点阵汉字字库是一种数字化储存汉字的方法,每个汉字被表示为一个16x16的点阵。这种汉字字库被广泛应用于计算机技术中,包括打印机,计算机文本编辑器和中英文输入法等。 16x16点阵汉字字库是一种极为精细的汉字数字化储存方式,能够保留汉字的每一个细节特征。每个点阵元素代表一个像素,点阵的每一个点都能够准确地呈现每个汉字轮廓线上的转角和曲线。这种设计方式,使得16x16点阵汉字字库在传输和呈现汉字时具有更高的准确性和清晰度。 随着计算机技术的飞速发展,16x16点阵汉字字库技术已被逐渐取代,目前更为流行的是基于向量的汉字数字储存方式。这种方案的主要特点是通过向量化的方式将汉字数字化,既准确又节省空间和传输成本。不过,16x16点阵汉字字库仍然在一些老旧的打印机和计算机系统中得到广泛使用。 ### 回答2: 16x16点阵汉字字库指的是一种字符编码方式,它将每个汉字用一个16x16的点阵图形表示出来,共包含了所有汉字的编码信息。这种编码方式早在上个世纪80年代就被广泛应用于计算机领域中,是中文字符编码系统中最广泛的一种。16x16点阵汉字字库中包含了常用汉字、繁体汉字、生僻字等各种汉字字符,对于中文输入法、打印机、标识牌等领域都有着重要的应用。同时,这种编码方式也有着一定的缺陷,如存储空间较大、相邻汉字可能会串码等问题。为了解决这些问题,现在的汉字编码方式已经逐渐演化出了多种不同的标准,如GB2312、GBK、GB18030等编码方式,不断完善与发展着。我们应认真学习和掌握这些编码方式,利用科技手段使中文文字的应用更加高效便捷。 ### 回答3: 16x16点阵汉字字库是一种常见的字库格式,它将每个汉字16x16个点的网格来表示,共计256个点。这种字库一般可以由计算机程序自动生成,也可以手工绘制。 由于16x16点阵汉字字库存储数据量较小,可以在较小的内存空间中快速加载,因此在一些嵌入式系统中广泛使用。在电子纸书、电子字典、数码相框、手写板等电子产品中,也经常使用16x16点阵汉字字库。 然而,由于该字库的显示效果不够清晰,有些汉字的细节不够清晰,所以在一些高端设备中,16x16点阵汉字字库已经被更高分辨率的字库所取代。目前,多种点阵和矢量字库汉字字体已经成为计算机操作系统和应用软件中的标准字体。 总的来说,16x16点阵汉字字库是一种广泛应用的字库格式,可以快速加载和节省内存空间,但其显示效果相对较差。在日常使用中,我们需要根据具体需求选择相应的汉字字库
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生命如歌,代码如诗

听说,打赏我的人都找到了真爱!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值