Unicode编码字符的点阵显示

本文介绍了一种将Unicode编码转换为GBK编码的方法,并详细描述了转换过程中的关键步骤,包括生成Unicode字符文件、制作Unicode到GBK的映射文件、排序、删除无用编码等。

对于unicode编码的字符,可以先将unicode编码转换为GBK编码,然后利用GBK点阵字库(gbk.bin)显示字符。一个比较好的编码转换方法是,制作一个按照unicode编码顺序排列的GBK编码表,直接根据unicode编码就可以查到对应的GBK编码,具体的制作方法如下:

1.生成一个unicode字符文件

上以篇文章中已经制作了一个GBK编码的全字符文件gbk.txt,用记事本打开gbk.txt,然后以unicode编码另存为unicode.txt文件。

这样的话,所有的GBK编码字符都用unicode编码保存在unicode.txt中了,可以用winhex打开unicode.txt,会发现前两个字节是FFFE,这是unicode编码的标识,要注意后面的unicode编码是小端存储。

2.制作unicode转gbk的文件

这里要用程序制作一个unicode与gbk编码相对应的文件,该文件每四个字节为一组,其中前两个字节为unicode编码,后两个字节是对应的gbk编码,两种编码都以小端存储,数据结构如下:

union code { unsigned int unigbk; unsigned short int uni_gbk[2]; unsigned char buffer[4]; };

这个数据结构是以gbk编码的顺序存放在文件uni2gbk.txt中,文件大小为128764Byte。程序如下:

//由unicode.txt和gbk.txt生成uni2gbk.txt #include <stdio.h> int main(void) { unsigned char buffer[2]; int count=0; FILE *fup=0; FILE *fgp=0; FILE *fwp=0; fup=fopen("unicode.txt","rb"); fgp=fopen("gbk.txt","rb"); fwp=fopen("uni2gbk.txt","wb"); fgetc(fup); fgetc(fup); while(1) { //读取unicode编码,写入uni2gbk.txt buffer[0]=fgetc(fup); buffer[1]=fgetc(fup); fputc(buffer[0],fwp); fputc(buffer[1],fwp); //读取gbk编码,写入uni2gbk.txt buffer[0]=fgetc(fgp); buffer[1]=fgetc(fgp); fputc(buffer[1],fwp); fputc(buffer[0],fwp); count+=2; if(count==0xfb7c) printf("xxxxxxxxx/n"); if(buffer[0]==0xfe && buffer[1]==0xfe) { printf("count = %x/n",count); fclose(fup); fclose(fgp); fclose(fwp); return; } } return 0; }

3.将uni2gbk.txt排序

用程序将uni2gbk.txt文件中的unioncode数据结构按照unicode编码的顺序从小到大排序,程序如下:

#include <stdio.h> #include <stdlib.h> #define MAXSIZE (0x7DBF) //union code的个数 union code { unsigned int unigbk; unsigned short int uni_gbk[2]; unsigned char buffer[4]; }; int main(void) { unsigned char flag=1; unsigned int i=0; unsigned int j=0; union code pdata; union code ndata; FILE *fp=0; fp = fopen("uni2gbk.txt","rb+"); for(i=1; i<MAXSIZE && flag==1; i++) { flag=0; for(j=0; j<(MAXSIZE-i); j++) { fseek(fp,j*4,0); fread(pdata.buffer,1,4,fp); fseek(fp,j*4+4,0); fread(ndata.buffer,1,4,fp); if(pdata.uni_gbk[0]>ndata.uni_gbk[0]) { flag=1; fseek(fp,j*4,0); fwrite(ndata.buffer,4,1,fp); fseek(fp,j*4+4,0); fwrite(pdata.buffer,4,1,fp); } } printf("i=%d/n",i); } fclose(fp); }

排序后,为了与没有排序的uni2gbk.txt区分,将文件名改为uni2gbkp.txt。

4.删除无用的编码

用winhex打开uni2gbkp.txt,可以发现,从0到第0x80EB个字节中的unicode编码都是0x0020或0x003F,这些都是无用的编码,它们所对应的gbk编码也是无用的,都可以删除。

删除后,uni2gbkp.txt文件中的unioncode数据结构的unicode编码就是从0x00A4开始,以0xFFE5结束。但是这些unicode编码不是连续的,例如0x00A4之后就是0x00A7,为了方便查找,需要在不连续的编码中间用unioncode填充,对应的gbk编码部分用0x0000填充,然后将unioncode中的unicode编码全部删除。最后生成uni2gbk.bin文件。程序如下:

#include <stdio.h> #include <stdlib.h> union code { unsigned int unigbk; unsigned short int uni_gbk[2]; unsigned char buffer[4]; }; int main() { unsigned short int count=0x00A4; //从unicode的0x00A4开始 union code temp; FILE *frp=0; FILE *fwp=0; frp=fopen("uni2gbkp.txt","rb"); fwp=fopen("uni2gbk.bin","wb"); fseek(frp,0x80EC,SEEK_SET); //舍弃uni2gbkp.txt文件的前0x80EC个字节 fread(temp.buffer,1,4,frp); while(count<=0xffe5) //以unicode的0xffe5结束 { if(temp.uni_gbk[0]==count) //判断unicode编码是否连续 { fputc(temp.buffer[2],fwp); //将对应的gbk编码写入uni2gbk.bin fputc(temp.buffer[3],fwp); fread(temp.buffer,1,4,frp); } else //不连续的地方填充0 { fputc(0x00,fwp); fputc(0x00,fwp); } count++; } fclose(frp); fclose(fwp); return 0; }

生成的uni2gbk.bin文件中都是gbk编码,这些gbk编码都是按照对应的unicode编码(0x00A4到0xFFE5)的顺序排列的。

5.uni2gbk.bin的使用

假设一个字符的unicode编码为X,那么它对应的gbk编码在uni2gbk.bin文件中的位置就是:

(X-0x00A4)*2

从这个位置读取一个unsignedshortint数据,就是它的gbk码。然后利用GBK点阵字库(gbk.bin)即可显示。

例如,以Linux的终端模拟点阵屏幕,程序如下:

#include <stdio.h> #include <unistd.h> #include <curses.h> #define START 0x8140 #define DATANUM 0x20 int displaychar(FILE *fp,unsigned short int dispch,char fillch,char start_x,char start_y); int main(void) { FILE * fp=0; unsigned short int testch = 0x7231; //汉字'爱‘的unicode码 unsigned short int gbkch=0; //存放testch的gbk编码 //将unicode转换为gbk fp = fopen("uni2gbk.bin","rb"); fseek(fp,(testch-0x00A4)*((unsigned int)2),SEEK_SET); gbkch = fgetc(fp); gbkch = (fgetc(fp)<<8) + gbkch; fclose(fp); fp = fopen("gbk.bin","rb"); initscr(); displaychar(fp,gbkch,'*',0,0); refresh(); while(1); endwin(); fclose(fp); return 0; } /* * fp指向点阵字库二进制文件 * 以点阵方式显示一个GBK字符 * dispch是要显示的字符,fillch是填充点阵的字符 * start_x,start_y是显示的起始坐标 */ int displaychar(FILE *fp,unsigned short int dispch,char fillch,char start_x,char start_y) { char x=start_x; char y=start_y; unsigned int location=(dispch-START)*DATANUM; int i=0; int j=0; char buf=0; fseek(fp,location,SEEK_SET); for(i=0;i<DATANUM;i++) { buf=fgetc(fp); //显示一个字节 for(j=0;j<8;j++) { move(y+j,x); if( buf & (0x01<<j) ) { addch(fillch); } } if(x == (start_x+15)) { x=start_x; y=start_y+8; } else x++; } return 0; }

下载:

unicode点阵字库文件:http://download.youkuaiyun.com/source/3362591

<!--EndFragment-->
v1.06 (20120410) FontMaker(点阵字库) 1. 增加系统字体支持,操作更简单,快捷。 v1.05 (20120324) FontMaker(点阵字库) 1. 修正了字符对齐问题。 2. 增加了单个字符或多个字符输出成位图文件设定。 3. 完善了阿拉伯文字库(unicode 字库有效)。 4. 增加自定义字符功能(unicode 字库有效)。 Multi-language(多国语言) 1. 增加输出编码格式 (mbcs, utf16-lb, utf8)设置 2. 增加数组格式输出。 Image Manager(图像管理) 1. 该页为新增功能,支持图片图像的数据转换。主要应用在做产品logo图片方面。 V1.04 (20110716) 1. 增加了一个字符串mbcs2unicode(内码转统一码)的功能。 (支持转:U16-LE, U16-BE, UTF8) V1.03 (20110705) 1. 修改了 Example 中点阵字库解析源码,更加便于移植。(基本做到只需修改font_file.c 即可) 2. 修改了内码(MBCS)字库点阵信息读取的一个错误。 3. 增加了多语言支持(简中,英文),还有待完善。。。 V1.02 (20110701) 1. FontMaker V2.03 a. 增加字符宽高比调节(HorR & VerR) b. 增加对*.ttc 字库的支持。 c. 增加bdf(*.bdf)文件格式转Simple Unicode编码格式的bin文件。 V1.01 (20110629) 1. FontMaker V2.02 a. 增加了 Simple Unicode功能。(适合小字库) b. 增加了 “扫描方向及反显”设置。 2. Multi-Language V1.01 a. 修改了除 office 2000 外,其它不能支持的问题。 V1.00: (20110627) 1. 继承 FontMaker V2.01 的所有功能。 2. 增加了一个 Multi-Languge V1.00 的打包转换功能。 FontMaker 基本功能: 1.支持所有 windows 字符集:CP932(日文Shift-JIS)CP936(简体中文GBK)CP949(韩文)CP950(繁体中文 Big5),CP874(泰文),CP1250(中欧)CP1251(西里尔文),CP1252(西欧--"拉丁文I"),CP1253(希腊文), CP1254(土耳其文),CP1255(希伯来文),CP1256(阿拉伯文),CP1257(波罗的海文),CP1258(越南) 2.支持非等宽字库。 3.支持BIN,TXT,BMP,BDF 文件输出。 4.支持unicode字库输出,即可以做到在一个窗口中同时显示多国语言(文字) 5.支持单个字符编辑,预览(所见即所得)。 6.支持字库文件和输出路径记忆功能 7. 支持从bdf格式转换自定义字库(bin文件)格式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值