Java 字体点阵算法

一、字模提取原理

无非就是从字库文件中读取出字模数据

以常用的HZK16字库文件为例:该字库文件是符合GB2312国家标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中一级汉字有 3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。

一个字节为8bit,用一个bit位来表示点阵中的一个点的话,16×16点阵需要16*16/8 = 32个字节才能达到显示一个普通汉字的目的。

GBK码也称为区位码,在字库文件中分为94个区。GB2312汉字都是由2字节组成的,第一个字节则是区码,第二个字节则是位码。

HZK16字库文件

汉字区码和位码的起始偏移量都为0xA1(不同的字库偏移量可能不同),故有如下计算公式:

偏移量 = (94*(区码-0xA1)+(位码-0xA1))*32;
ASC16字库文件

在ASC16字库文件中,没有区位的说法,其偏移量就是ASCII码值。由于是ASCII字符,只占1个字节,其宽度只有8。故一个ASCII字符占用16*8/8=16个字节数据。故有如下公式:

偏移量 = ASCII码值*16;

二、图示

汉字 "强"  (0x7CBF)

ASCII值 "2" (0x32)

三、示例代码

1. 汉字 HZK16 字模提取  16*16
#include<stdio.h>
#include <string.h>

void Bytes_Read_from_HZK( unsigned char *s, char * chs)
{
	FILE *fp;
	unsigned long offset;
	int ret = 0;
	int i = 0;
	int j = 0;
	int k = 0;
	unsigned char key[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
	//offset = ((s[0] - 0xb0) * 94 + (s[1] - 0xa1)) * 32; //根据内码找出汉字在HZK中的偏移位置,不同的字库可能偏移位置不同
	offset = (94*(unsigned int)(s[0]-0xA1)+(s[1]-0xA1))*32;
	if ((fp = fopen("HZK16", "rb+")) == NULL)
		return; //打开字库文件

	fseek(fp, offset, SEEK_SET); //文件指针偏移到要找的汉字处
	ret = fread(chs, 32, 1, fp); //读取该汉字32个字节的字模数据
	printf("ret = %d\n",ret);
	for(k=0; k<16; k++)
	{
		for(j=0; j<2; j++)
		{
			for(i=0; i<8; i++)
			{
				int flag = chs[k*2+j]&key[i];
				printf("%s", flag?"● ":"○ ");//将单个字节每个bit位的状态显示出来
			}
		}
		printf("\n");
	}
	fclose(fp);
}
int main(int argc,char *argv[])
{
	char s[2]={0xC7,0xBF};//强
	char chs[32]={0};
	char table1[16]={0};
	char table2[16]={0};
	//	memset(chs,0,32);
	int i = 0;
	int k = 0;
	int j = 0;
	Bytes_Read_from_HZK( s, chs );
	for(i = 0; i<32; i++)
	{	
		if( i % 2 == 0 )
			table1[j++] = chs[i];   //由于LED扫描方式的需要,故对数据分组进行处理,调换排列顺序并取反
		else
			table2[k++] = chs[i];
	}
	for(i = 0; i<16 ;i++) 
	{
		printf("0x%02X,", (unsigned char)(~table1[i]));  //数据取反
	}
	printf("\n");
	for(i = 0; i<16 ;i++)
	{
		printf("0x%02X,", (unsigned char)(~table2[i]));
	}
	printf("\n");
	return 0;
}
2. 数字、字母 ASC16 字模提取  16*8
#include<stdio.h>
#include <string.h>

void Bytes_Read_from_HZK( unsigned char *s, char * chs)
{
	FILE *fp;
	unsigned long offset;
	int ret = 0;
	int i = 0;
	int j = 0;
	int k = 0;

	unsigned char key[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
	offset = (*s) * 16;   //找出在字库中的偏移位置
	if ((fp = fopen("ASC16", "r+")) == NULL)
	{
		printf("open fail!!\n");
		return; //打开字库文件
	}

	fseek(fp, offset, SEEK_SET); //文件指针偏移到要找的字符处
	ret = fread(chs, 16, 1, fp); //读取该字符的字模
	printf("ret = %d\n",ret);
	
	for(k=0; k<16; k++)
	{
		for(i=0; i<8; i++)
		{
			int flag = chs[k]&key[i];
			printf("%s", flag?"● ":"○ ");
		}
		printf("\n");
	}
	fclose(fp);
}

int main(int argc,char *argv[])
{
	char s[1]={0x32};//数字 "2"
	char chs[16]={0};
	int i = 0;
	int k = 0;
	int j = 0;
	Bytes_Read_from_HZK(s, chs);
	for(i = 0; i<16; i++)
	{
		printf("0x%02X,", (unsigned char)(~chs[i]));
	}
	printf("\n");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值