中文字符点阵信息的显示和插入新字符(基于HZK16 ASC16软字库)

本系统是对中文字库HZK16和ASC16字库进行操作

HZK16字库中每一个中文字符使用的是32字节的点阵信息,ASC16字库是16字节的点阵信息打印

本文实现了中文汉字的点阵信息打印和字符的操作,包括插入未知字符(囧)(需要借助软件PCtoLCD.exe实现点阵信息的提取)


/**************************************************************************
** this C source code is made for HZK16 and ASC16 characters system ***
**                  ***
**            newplan 2013.9   in UESTC     ***
**************************************************************************/
#include 
#include 
#include 
#define FONTSIZE 32

//typedef unsigned int    WORD;
//typedef unsigned char   BYTE;

/**********************************************************************************************/
int Get_Asc_Code(unsigned char *Get_Input_Char, char buff[]);
int Get_HzK_Code(unsigned char *Get_Input_Char, char buff[]);
void Print_Asc_Char(char *mat, char *Out_Put_1, char *Out_Put_2);
void Print_HzK_Char(char *mat, char *Out_Put_1, char *Out_Put_2);
unsigned long Judge_type_char(unsigned char *Get_Input_Char, unsigned long *offset, int *length);
int Delete_Char_From_Lib(char *character, unsigned long offset, char *Lib_Name);
int Get_Char_Model(unsigned char buff_input[FONTSIZE * FONTSIZE / 8]);
int Not_In_Lib(char buff[FONTSIZE * FONTSIZE / 8]);
int transpose(char chaned[FONTSIZE][FONTSIZE]);
void distranspose(char mat[][FONTSIZE / 8], char **array);
int asistant_insert(unsigned char *mat);
void change(char mat[][FONTSIZE / 8], char **array);
/**********************************************************************************************/

int output_system(void);
int insert_system(void);
int delete_system(void);




//*******************************************************************
// Method:    Get_Asc_Code
// FullName:  Get_Asc_Code
// Access:    public
// Returns:   int
// Qualifier: 得到英文字符的字模信息,存入数组
// Parameter: unsigned char * Get_Input_Char 要得到字模信息的字符指针
// Parameter: char buff[] 存储得到字模信息的数组
//********************************************************************
int Get_Asc_Code(unsigned char *Get_Input_Char, char buff[])
{
	unsigned long offset;
	FILE *ASC;
	/*打开字库文件asc16*/
	if ((ASC = fopen("ASC16", "rb+")) == NULL)
	{
		printf("Can't open asc,Please add it?");
		system("pause");
		exit(0);
	}
	offset = *(Get_Input_Char) * 16 + 1;         /*通过ascii码算出偏移量*/
	fseek(ASC, offset, SEEK_SET);                /*将文件指针移动到偏移量的位置*/
	fread(buff, 16, 1, ASC);                     /*从偏移量的位置读取32个字节*/
	printf("ASCII:%d,offset:%d \n\r", *Get_Input_Char, offset);
	fclose(ASC);
	return 1;
}

//*****************************************************************************
// Method:    Print_Asc_Char
// FullName:  Print_Asc_Char
// Access:    public
// Returns:   void
// Qualifier: 根据字模信息输出英文字符
// Parameter: char * mat 字模指针
// Parameter: char * Out_Put_1 字模中为1的点显示的字符,也就是前景字符
// Parameter: char * Out_Put_2 字模中为0的点显示的字符,也就是背景字符
//***************************************************************
void Print_Asc_Char(char *mat, char *Out_Put_1, char *Out_Put_2)
{
	int i, j;
	for (i = 0; i < 16; i++)          /* 8x16的点阵,一共有16行*/
	{
		for (j = 0; j < 8; j++)         /*横向一个字节8位,依次判断每位是否为0*/
			if (mat[i] & (0x80 >> j))   /*测试当前位是否为1*/
				printf("%s", Out_Put_1);      /*为1的显示为字符c1*/
			else printf("%s", Out_Put_2);      /*为0的显示为字符c2*/
		printf("\n");                   /*输完一行以后,进行换行*/
	}
}

/***************************************************************************/
// Method:    Get_HzK_Code                                               ***
// FullName:  Get_HzK_Code                                               ***
// Access:    public                                                     ***
// Returns:   int                                                        ***
// Qualifier: 得到汉字字符的字模信息,存入数组                           ***
// Parameter: unsigned char * Get_Input_Char 要得到字模信息的字符指针 ***
// Parameter: char buff[] 存储字模信息的数组                           ***
/***************************************************************************/
int Get_HzK_Code(unsigned char *Get_Input_Char, char buff[])
{
	int not_find = 0;
	unsigned char qh, wh;
	unsigned long offset;
	FILE *HZK;
	char file_name[] = "HZK32";
	if ((HZK = fopen(file_name, "rb+")) == NULL) /*打开字库文件hzk16*/
	{
		printf("Can't open %s,Please add it?\n", file_name);
		system("pause");
		exit(0);
	}
	/*区码=内码(高字节)-160  位码=内码(低字节)-160*/
	qh     = *(Get_Input_Char) - 0xa0;           /*10进制的160等于16进制的A0*/
	wh     = *(Get_Input_Char + 1) - 0xa0;       /*获得区码与位码*/
	offset = (94 * (qh - 1) + (wh - 1)) * FONTSIZE * FONTSIZE / 8; /*计算该汉字在字库中偏移量*/
	not_find = fseek(HZK, offset, SEEK_SET); /*将文件指针移动到偏移量的位置*/
	if (not_find)
	{
		printf("未查到该区!error!!!\n");
		fclose(HZK);
		return 0;
	}
	fread(buff, FONTSIZE * FONTSIZE / 8, 1, HZK);    /*从偏移量的位置读取32个字节*/
	if (Not_In_Lib(buff))
	{
		fclose(HZK);
		printf("有未识别字符!\n");
		system("pause");
		return 0;
	}
	printf("qh:%d,wh:%d,offset:%ld\n\r", qh, wh, offset);
	fclose(HZK);
	return 1;
}

//**************************************************************************
// Method:    Print_HzK_Char                                             ***
// FullName:  Print_HzK_Char                                             ***
// Access:    public                                                     ***
// Returns:   void                                                       ***
// Qualifier: 根据字模信息输汉字字符                                   ***
// Parameter: char * mat 字模指针                                        ***
// Parameter: char * Out_Put_1 字模中为1的点显示的字符,也就是前景字符  ***
// Parameter: char * Out_Put_2 字模中为0的点显示的字符,也就是背景字符  ***
//**************************************************************************
void Print_HzK_Char2(char *mat, char *Out_Put_1, char *Out_Put_2)
{
	int i, j, k;
	for (i = 0; i < FONTSIZE; i++)          /*16x16点阵汉字,一共有16行*/
	{
		for (j = 0; j < FONTSIZE / 8; j++)       /*横向有2个字节,循环判断每个字节的*/
			for (k = 0; k < 8; k++)       /*每个字节有8位,循环判断每位是否为1*/
				if (mat[i * FONTSIZE / 8 + j] & (0x80 >> k)) /*测试当前位是否为1*/
					printf("%s", Out_Put_1);         /*为1的显示为字符c1*/
				else printf("%s", Out_Put_2);     /*为0的显示为字符c2*/
		printf("\n");                   /*输完一行以后,进行换行*/
	}
}

void Print_HzK_Char(char *mat, char *Out_Put_1, char *Out_Put_2)
{
	int i, j, k;
	for (j = 0; j < FONTSIZE / 8; j++)       /*横向有2个字节,循环判断每个字节的*/
		for (k = 0; k < 8; k++)       /*每个字节有8位,循环判断每位是否为1*/
		{
			for (i = 0; i < FONTSIZE; i++)          /*16x16点阵汉字,一共有16行*/
			{
				if (mat[i * FONTSIZE / 8 + j] & (0x80 >> k)) /*测试当前位是否为1*/
					printf("%s", Out_Put_1);         /*为1的显示为字符c1*/
				else printf("%s", Out_Put_2);     /*为0的显示为字符c2*/
			}
			printf("\n");                   /*输完一行以后,进行换行*/

		}
}

//*****************************************
// Method:    Not_In_Lib          ***
// FullName:  Not_In_Lib          ***
// Access:    public           ***
// Returns:   int            ***
// Qualifier: /*判断字符是不是在字库里  ***
// Parameter: char buff[]          ***
//*****************************************
int Not_In_Lib(char buff[FONTSIZE * FONTSIZE / 8])
{
	for (int i = 0; i < FONTSIZE * FONTSIZE / 8; i++)
	{
		if (buff[i])   //如果有一个不为0,表明buff【】已经被修改过,字库存在此字退出此函数
			return 0;
	}
	return 1;
}

//******************************************************************
// Method:    Select_type_char                 ***
// FullName:  Select_type_char                ***
// Access:    public                  ***
// Returns:   int 0 表示成功;                 ***
// Qualifier: 判断是中文字符还是英文单字节字符,并算出偏移量  ***
// Parameter: unsigned char * Get_Input_Char            ***
// Parameter: int * offset 偏移量                ***
// Parameter: int * length 缓冲区的长度          ***
//******************************************************************
unsigned long Judge_type_char(unsigned char *Get_Input_Char, unsigned long *offset, int *length)
{
	if (Get_Input_Char[2] == 0 && Get_Input_Char[1] == 0) //asc16
	{
		*offset = *(Get_Input_Char) * 16 + 1;
		*length = 16;
	}
	else         //HZK16
	{
		unsigned char qh     = (unsigned char)Get_Input_Char[0] - 0xa0;         /*10进制的160等于16进制的A0*/
		unsigned char wh     = (unsigned char)Get_Input_Char[1] - 0xa0;         /*获得区码与位码*/
		*offset = (94 * (qh - 1) + (wh - 1)) * 32L; /*计算该汉字在字库中偏移量*/
		*length = 32;
	}
	return *offset;
}

//**************************************************************
// Method:    Get_Char_Model            ***
// FullName:  Get_Char_Model             ***
// Access:    public              ***
// Returns:   int 0 表示字模读取失败 1表示读取成功     ***
// Qualifier: 区汉字字模             ***
// Parameter: unsigned char * character 指向一个要加入字库的字符
// Parameter: char buff_input   指向字模的指针   ***
//**************************************************************
int Get_Char_Model( unsigned char buff_input[FONTSIZE * FONTSIZE / 8])
{
	char st[] = "C:/experience/PCtoLCD/PCtoLCD2002.exe"; // 已给定命令内容的字符变量
	char file_read_buffer[2000];
	FILE * model_read_stream;
	int number = 0, current = 0, decade = 0, bits = 0;
	memset(file_read_buffer, 0, sizeof(file_read_buffer));
	printf("保存的字模文件请务必以:model.TXT文件名保存\n");
	printf("读取汉字字模应用程序即将打开!\n");

	system("pause");
	system(st);   // 运行文件PCtoLCD.exe
	model_read_stream = fopen("C:/experience/PCtoLCD/lib/model.TXT", "r");
	if (!model_read_stream)
	{
		printf("文件打开失败!\n");
		return 0;
	}
	fread(file_read_buffer, sizeof(file_read_buffer), sizeof(char), model_read_stream);
	system("pause");
	printf("\n%s\n", file_read_buffer);
	fclose(model_read_stream);
// system("del C:/experience/PCtoLCD/lib/model.TXT");
// system("del C:/experience/PCtoLCD/lib/model.TXT_index.TXT");
	printf("wait for a minute!\n");
	system("pause");
	for (current = 0; current < sizeof(file_read_buffer); current++)
	{
		if (file_read_buffer[current] == 'H')
		{
			decade = file_read_buffer[current - 2] < 'A' ?
			         file_read_buffer[current - 2] - '0' : file_read_buffer[current - 2] - 'A' + 10;
			bits = file_read_buffer[current - 1] < 'A' ?
			       file_read_buffer[current - 1] - '0' : file_read_buffer[current - 1] - 'A' + 10;
			buff_input[number] = (unsigned char)(decade * FONTSIZE + bits);
			number++;
		}
		if (number >= FONTSIZE * FONTSIZE / 8)
			return 1;
	}
	return 0;
}

//*********************************************************
// Method:    Delete_Char_From_Lib						***
// FullName:  Delete_Char_From_Lib						***
// Access:    public									***
// Returns:   int 										***
// Qualifier: 删除字库中的某个文字						***
// Parameter: unsigned char * character  要删除的字符 	***
// Parameter: int offset    删除字符的偏移量			***
// Parameter: char * Lib_Name   删除字符的库			***
//*********************************************************
int Delete_Char_From_Lib(char *character, unsigned long offset, char *Lib_Name)
{
	char buff_clear_chinese[32], buff_clear_english[16];
	memset(buff_clear_chinese, 0, sizeof(buff_clear_chinese));
	memset(buff_clear_english, 0, sizeof(buff_clear_english));
	FILE *open_file = fopen(Lib_Name, "rb+");
	fseek(open_file, offset, SEEK_SET);
	if (!open_file)
	{
		printf("can`t open file: %s\n", Lib_Name);
		exit(0);
	}
	if (character[2] == 0 && character[1] == 0)
	{
		fwrite(buff_clear_english, 16, 1, open_file);
	}
	else
	{
		system("pause");
		fwrite(buff_clear_chinese, 32, 1, open_file);
	}
	printf("delete successfully!\n");
	fclose(open_file);
	system("pause");
	return 0;
}

//*****************************************************************
// Method:    transpose           ***
// FullName:  transpose           ***
// Access:    public           ***
// Returns:   int            ***
// Qualifier: 转置函数                                          ***
//因为字模软件读取的汉字按照正常运算是被转置的          ***
// Parameter: char changed[16][16]        ***
//*****************************************************************
int transpose(char changed[FONTSIZE][FONTSIZE])
{
	char temp;
	int i = 0, j = 0;
	for (i; i < FONTSIZE; i++)
	{
		for (j = i; j < FONTSIZE; j++)
		{
			temp = changed[i][j];
			changed[i][j] = changed[j][i];
			changed[j][i] = temp;
		}
	}
	return 1;
}

//************************************
// Method:    distranspose
// FullName:  distranspose
// Access:    public
// Returns:   void
// Qualifier: /*把二进制的mat数组转变成字符change数组*/
// Parameter: char mat[][2]
// Parameter: char * * array
// Parameter: int m
// Parameter: int n
//************************************
void distranspose(char mat[][FONTSIZE / 8], char **array)
{
	int i, j, k, l = 0, n = FONTSIZE;
	for (i = 0; i < FONTSIZE; i++)
	{
		for (j = 0; j < FONTSIZE / 8; j++)
		{
			for (k = 0; k < 8; k++)
			{
				if (*((char*)array + n * i + l) == '#') //根据每个字节的0和1的状态计算出可用的字模
				{
					mat[i][j] |= (0x80 >> k);
				}
				else
				{
					mat[i][j] &= (~(0x80 >> k));
				}
				l++;
			}
		}
		l = 0;
	}
	return ;
}

//************************************
// Method:    change
// FullName:  change
// Access:    public
// Returns:   void
// Qualifier: /*把二进制的mat数组转变成字符change数组*/
// Parameter: char mat[][2]
// Parameter: char * * array
// Parameter: int m
// Parameter: int n
//************************************
void change(char mat[][FONTSIZE / 8], char **array)
{
	int i, j, k, l = 0, n = FONTSIZE;
	for (i = 0; i < FONTSIZE; i++)
	{
		for (j = 0; j < FONTSIZE / 8; j++)
		{
			for (k = 0; k < 8; k++)
			{
				if (mat[i][j] & (0x80 >> k)) //提出每个字节的0和1的状态
				{
					*((char*)array + n * i + l) = '#';
					l++;
				}
				else
				{
					*((char*)array + n * i + l) = '-';
					l++;
				}
			}
		}
		l = 0;
	}

	return ;
}


//************************************
// Method:    asistant_insert
// FullName:  asistant_insert
// Access:    public
// Returns:   int
// Qualifier: 辅助插入字符函数
// Parameter: unsigned char * mat
//************************************
int asistant_insert(unsigned char *mat)
{
	int j = 0, i = 0;
	char array[FONTSIZE][FONTSIZE], mat_temp[FONTSIZE][FONTSIZE / 8];

	memset(array, 0, sizeof(array));
	memset(mat_temp, 0, sizeof(mat_temp));

	for (j = 0, i = 0; j < FONTSIZE; j++)
	{
		mat_temp[j][0] = mat[i];
		mat_temp[j][1] = mat[i + 1];
		mat_temp[j][2] = mat[i + 2];
		mat_temp[j][3] = mat[i + 3];
		i = i + FONTSIZE / 8;
	}
	change(mat_temp, (char **)array);
	transpose(array);
	distranspose(mat_temp, (char **)array);
	for (j = 0, i = 0; j < FONTSIZE; j++)
	{
		mat[i] = mat_temp[j][0];
		mat[i + 1] = mat_temp[j][1];
		mat[i + 2] = mat_temp[j][2];
		mat[i + 3] = mat_temp[j][3];
		i = i + FONTSIZE / 8;
	}
	return 0;
}



//************************************
// Method:    out_put_system
// FullName:  out_put_system
// Access:    public
// Returns:   int
// Qualifier: 显示输出系统(包括中英文字符)
// Parameter: void
//************************************
int output_system(void)
{
	int count = 0;
	char Buffer_English[16], Buffer_Chinese[FONTSIZE * FONTSIZE / 8];
	unsigned char word[3] = {0};
	char *Output_String1 = (char *)"●", *Output_String2 = (char *)"○";
	while (1)
	{
		memset(Buffer_Chinese, 0, sizeof(Buffer_Chinese));
		memset(Buffer_English, 0, sizeof(Buffer_English));
		printf("输入要生成字模的汉字(可以多个输入)[Q表示退出]:");
		for (;;)
		{
			word[2] = getchar();

			/*************************************************************************
			**根据汉字编码的规定,汉字字符使用双字节表示,而且第一个字节的表示成数字是   **
			**大于128,根据getchar()是否大于128可以判断出是单字节字符还是双字节字符   **
			**另外根据计数变量count计算出当前操作的字符是双字节字符还是单字节字符。。   **
			*************************************************************************/
			if (((unsigned char)word[2] < 128) && (count % 2 == 0))
			{
				if (word[2] == '\n')
				{
					break;
				}
				else if (word[2] == 'Q')
				{
					getchar();
					fflush(stdin);
					return 1;
				}
				if (Get_Asc_Code(&word[2], Buffer_English))
				{
					Print_Asc_Char(Buffer_English, Output_String1, Output_String2);
					memset(Buffer_English, 0, sizeof(Buffer_English));
				}
				continue ;
			}
			if ((count % 2) == 0)
			{
				word[0] = word[2];
				count++;
				continue;
			}
			word[1] = word[2];
			word[2] = 0;
			count++;
			if (Get_HzK_Code(word, Buffer_Chinese))
			{
				Print_HzK_Char(Buffer_Chinese, Output_String1, Output_String2);
				memset(Buffer_Chinese, 0, sizeof(Buffer_Chinese));
			}
			else continue;
		}
	}
	return 0;
}

//************************************
// Method:    insert_system
// FullName:  insert_system
// Access:    public
// Returns:   int
// Qualifier: 插入字符
// Parameter: void
//************************************
int insert_system(void)
{
//变量申明部分
	char get_char[3];
	FILE *fp = NULL;
	int not_find = 0;
	unsigned char qh, wh;
	unsigned long offset;
	char buff[FONTSIZE * FONTSIZE / 8];
	char file_name[] = "HZK32";
	memset(get_char, 0, sizeof(get_char));
	printf("请输入您想加入字库的字:");
	gets(get_char);
	if (strcmp(get_char, "ZZ") <= 0)
	{
		printf("您输入了非法字符!\n");
		system("pause");
		return 0;
	}
	if ((fp = fopen(file_name, "rb+")) == NULL) /*打开字库文件hzk16*/
	{
		printf("Can't open haz16,Please add it?");
		system("pause");
		exit(0);
	}
	/*区码=内码(高字节)-160  位码=内码(低字节)-160*/
	qh     = (unsigned char)get_char[0] - 0xa0;           /*10进制的160等于16进制的A0*/
	wh     = (unsigned char)get_char[1] - 0xa0;         /*获得区码与位码*/
	offset = (94 * (qh - 1) + (wh - 1)) * FONTSIZE * FONTSIZE / 8; /*计算该汉字在字库中偏移量*/
	not_find = fseek(fp, offset, SEEK_SET); /*将文件指针移动到偏移量的位置*/
	if (not_find)
	{
		printf("未查到该区!error!!!\n");
		fclose(fp);
		return 0;
	}
	memset(buff, 0, sizeof(buff));
	fread(buff, FONTSIZE * FONTSIZE / 8, 1, fp);    /*从偏移量的位置读取32个字节*/
	if (!Not_In_Lib(buff))
	{
		printf("字库HZK16存在此字!!!\n");
		system("pause");
		fclose(fp);
		return 0;
	}
	fseek(fp, offset, SEEK_SET); //重置字库中的偏移量
	unsigned char buff_time[FONTSIZE * FONTSIZE / 8];
	memset(buff_time, 0, sizeof(buff_time));
	if (!Get_Char_Model(buff_time))
	{
		printf("字模读取失败\n");
		fclose(fp);
		return 0;
	}
	asistant_insert(buff_time);
	fwrite(buff_time, FONTSIZE * FONTSIZE / 8, 1, fp) ? printf("字符加入成功!\n") : printf("字符加入失败!\n");
	printf("qh:%d,wh:%d,offset:%ld\n\r", qh, wh, offset);
	system("pause");
	fclose(fp);
	return 0;
}

//************************************
// Method:    delete_system
// FullName:  delete_system
// Access:    public
// Returns:   int
// Qualifier: 删除字符部分
// Parameter: void
//************************************
int delete_system(void)
{
	char character[3], *lib_name;
	int length = 0;
	unsigned long offset = 0;
	memset(character, 0, sizeof(character));
	lib_name = (char *)malloc(30 * sizeof(char));
	memset(lib_name, 0, sizeof(lib_name));
	printf("输入您要删除的字符:");
	gets(character);
	offset = Judge_type_char(character, &offset, &length);
	if (length == 16)
	{
		strcat(lib_name, "ASC16");
	}
	else
	{
		strcat(lib_name, "HZK16");
	}
	Delete_Char_From_Lib(character, offset, lib_name);
	return 0;
}

//************************************
// Method:    main
// FullName:  main
// Access:    public
// Returns:   int
// Qualifier: 函数入口
// Parameter: void
//************************************
int main(void)
{
	char choice[2] = {0, 0};
	int number = -1;
	for (;;)
	{
		printf("\n\tEmbedded Characters Processing Program\n");
		printf("\t\t\tmade by NEWPLAN\n");
		printf("\t\t\t2013.9 in UESTC\n");
		printf("\t MENU\n\n");
		printf("\t0:退出程序\n");
		printf("\t1:字符显示\n");
		printf("\t2:字符删除\n");
		printf("\t3:添加字符\n");
		printf("\t4:清理屏幕\n");
		printf("your choice=");
		gets(choice);
		number = atoi(choice);
		fflush(stdin);
		switch (number)
		{
		case 0 :
			printf("退出程序!\n");
			system("pause");
			return 0;
		case 1  :
			output_system();
			break;
		case 2  :
			delete_system();
			break;
		case 3 :
			insert_system();
			break;
		case 4 :
			system("cls");
			break;
		default :
			printf("错误输入!\n\n");
			break;
		}
		number = -1;
	}
	return 0;
}

测试结果:

中文字符点阵信息的显示和插入新字符(基于HZK16 ASC16软字库)_第1张图片



你可能感兴趣的:(project,c语言,源码)