LED点阵字模提取学习

一、字模提取原理

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

以常用的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)

三、LED扫描方式、顺序、方向、阴阳码

得到字模数据后大多数情况不能直接使用,因为LED屏幕大部分情况下是以动态刷新的方式来显示的,字模数据需要根据LED显示屏的扫描方式进行调整,才能满足不同系统的要求,其实无非就是调换字模数据的排列顺序或者对字模数据取反。

四、示例代码

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;
}

五、相关参考资料传送门:

汉字GBK码查询:

http://www.mytju.com/classCode/tools/encode_gb2312.asp

字模提取参考示例:

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

字模提取原理:

https://wenku.baidu.com/view/c2b10f1eb7360b4c2e3f6443.html

字模提取软件:

http://www.eeworld.com.cn/mcu/article_2016121532319.html

字库文件下载:

https://pan.baidu.com/s/1He74KkqMl5aqsXY51Ttq_g

猜你喜欢

转载自blog.csdn.net/fangye945a/article/details/84798737