1. 程式人生 > >LED點陣字模提取學習

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