本系统是对中文字库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;
}