汉字的编码与字模点阵小结
作者: laomai
url:  http://blog.csdn.net/laomai
转载时请注明出处
一、引言
今天是三八节,为了祝一个mm节日快乐,
自己动手写了一个简单的字符灌水机,
运行效果如下图(csdn的blog好象对空格可以自动过滤,

大家凑活着看吧,反正只要给MM看的时候显示正常就行:-)

节      节
节节节节节节节节节节节
      节      节
      节      节
  节节节节节节节节节
        节        节
        节        节
        节        节
        节  节节节
        节
        节

日日日日日日日日
    日            日
    日            日
    日            日
    日日日日日日日日
    日            日
    日            日
    日            日
    日            日
    日日日日日日日日
    日            日

快        快
  快        快
  快    快快快快快快
快快快      快    快
快快  快    快    快
  快        快    快
  快  快快快快快快快快
  快        快
  快      快  快
  快    快      快
  快快快          快快
           
            乐乐乐
    乐乐乐乐
    乐      乐
    乐      乐
  乐        乐    乐
  乐乐乐乐乐乐乐乐乐乐
      乐    乐乐
    乐      乐  乐
  乐        乐    乐
乐          乐      乐
        乐乐乐  
在写程序的过程中顺便把汉字内码、编码和点阵的概念理了一下,
这里把心得发出来,欢迎大家拍砖.

二、汉字的内码、编码和点阵
汉字显示的基本原理,计算机内一般都有汉字的字模库(也就是我们所说的点阵).
在dos下显示汉字的基本过程是
⑴计算机首先得到汉字的内码,这个就是存储在文本文件中的16进制数字,
⑵由内码计算出汉字的区位码
⑶由区位码得到字库文件中汉字点阵的真实位置
⑷按点阵(坐标)信息在屏幕上的对应位置打点,就形成了我们看到的汉字字符

下面具体说一下其中的几个概念
1、内码
   内码就是汉字在计算机上存储时的编码,比如我们写一个文本文件,内容为
   "节日快乐",用16进制编辑器打开它,其内容为
   BD DA C8 D5 BF EC C0 D6
   这里的bd da就是第一个汉字"节"的内码.

2、区位码
   区位码是国标gb2312中规定的汉字编码,这个是用来指导字库(点阵)文件
的国家标准,不同的字库文件(比如12*12,16*16,24*24),其显示用来的点阵
规模不共同,但是存储汉字的顺序都是一致的。这个会在后面会举例说明。
 我们要知道的是,gb2312规定的区位码实际上就是一个94×94的矩阵。
在此方阵中,每一行称为一个”区”,每一列称为一个”位”,
因此,这个方阵实际上组成了一个有94个区(编号范围为十进制的1到94)、
每个区内有94个位(编号范围为1到94)的汉字字符集。
一个汉字所在的区号和位号简单地组合在一起就构成了该汉字的”区位码”。
在汉字的区位码中,高两位为区号,低两位为位号。
比如"节"的区位码为
 节 2958
其中  区码为29,也就是16进制的1D
   位码为58, 也就是16进制的3A
所有汉字的区位码可以在下面的网址查到
http://www.knowsky.com/resource/gb2312tbm.htm

3、内码与区位码的转换
 内码高位=区码+A0(也就是10进制的160)
 内码低位=位码+A0
 
我们用"节"字来验证一下,
    内码低位为 DA = 区码3A+A0
    内码高位为 BD = 位码1D+A0
注意在intel的机器上,内码的高位存储在低地址上,低位存储在高地址上.

4、点阵
 对计算机而言,每个汉字其实是一个点的方阵,
 标0的位置涂黑(背景色),标1的位置涂白(前景色),
 使这个方阵在屏幕看起来象一个汉字而已。比如"一"字,
 其12*12字库文件中的点阵信息为
 000000000000
 000000000000
 000000000000
 000000000000
 000000000100
 111111111110
 000000000000
 000000000000
 000000000000
 000000000000
 000000000000
 000000000000
 计算机在把汉字输出到显示设备上时,就按照点阵中的信息在屏幕的
对应位置上涂色,标0的涂背景色(默认为黑色),标0的涂前景色(默认为白色)
就形成了我们在屏幕上看到的汉字。

5、字库文件
    要显示汉字,就必须得到它的点阵信息,而前面说过,汉字的点阵信息是按照区位码的顺序存储在字库文件中的。所以要想取出某个汉字的点阵信息,就必须知道该汉字在字库中的位置,这个位置的计算公式为
 94*(区号-1)+位号-1
 减1是因为文件中的偏移量是以0为开始而区号位号是以1为开始的,需要换算一下。
 不过现在得到的还只是该汉字在字库中的位置,要得到在字模文件中的具体存储位置
 还要乘上一个汉字字模占用的字节数。
 一个汉字字模站用的字节数就是其点阵占用的的字节数,比如对12*12字模,
占用的 字节数就是12*12/8=16字节.
 
综合起来,一个汉字点阵在字库文件中的存储位置计算公式为
 (94*(区号-1)+位号-1)*(单个字模的字节数)
 而 单个字模的字节数=点阵的行数*点阵的列数/一个字节所占的位数

三、实现简单的字符灌水机         
了解了以上的预备知识,我们就可以输出汉字点阵信息的程序了。代码如下

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

const int reglen = 94;       //每区(行)有 94 位(列)
const int font_width  = 12;  // 单字点阵宽度(列数)
const int font_height = 12;  // 单字点阵高度(行数)
const int dotsize = font_width * font_height /8;   //一个汉字点阵所占的字节数
const int subcode = 0xa0;      //内码与区、位码的差值

char *font_file_name  = "simsun12.fon"; // 点阵字库文件名
char str[] = "一";    //要显示点阵信息的汉字
char bindot[dotsize] = ...{0};   //存储点阵信息的数组

void printcharbindot(char* bindot, int dotlen);
int main(int argc, char* argv[])
...{
    FILE *fp = fopen(font_file_name, "rb");
    int string_size = font_width * font_height;

    int i=0,j=0;
    unsigned char regcode;  //区码
    unsigned char bitcode;  //位码 

    // 计算区位码,
    regcode = (unsigned char) str[i] - subcode;
    bitcode = (unsigned char) str[i+1] - subcode;

    //再计算汉字在字库中的位置,进而得出此字符点阵在字体文件中的偏移
    int offset = ( (regcode-1) * reglen + bitcode-1) * dotsize;
    
    // 在字库文件中读取其点阵数据
    fseek(fp, offset, SEEK_SET);
    fread(bindot, sizeof(bindot),1, fp);
    
    //输出其点阵信息
    printcharbindot(bindot, dotsize);
    
    fclose(fp);
    system("pause");
    return 0;
}

//按顺序输出点阵的每一位信息
void printcharbindot(char* bindot, int len)
...{
    int charnum = 0;  //当前字节号
    int bitnum  = 0;  //已读取的位数
    int bitindex =0;  //当前位号
    int bitvalue;     //当前位的值
    for (charnum =0; charnum < len; ++charnum)
    ...{
        //从高到低顺次输出一个字节的每位信息
        for(bitindex = 7;bitindex>=0; --bitindex)
        ...{
            //输出当前字节第bitindex位的值
            bitvalue  = ((bindot[charnum]>>bitindex) & 0x1 );  
            printf("%c", bitvalue+'0');

            //满12位输出一行
            if ((++bitnum %12) == 0)
                printf(" ");
        }
    }
}

运行时用到的字库文件simsun12.fon可以到这里下载
http://www.ugia.cn/wp-data/fontfun.rar

运行结果为
000000000000
000000000000
000000000000
000000000000
000000000100
111111111110
000000000000
000000000000
000000000000
000000000000
000000000000
000000000000

这个程序稍加改动,就可以做出我们前面所说的字符灌水机了,
请读者自行实现.

四、致谢
在写这篇学习笔记的时候参考了以下两篇文章中的内容,在此向这两篇
文章的作者表示钦佩和感谢.
实现代码的部分参考了
http://www.ugia.cn/?p=82    作者legend
区位码和点阵部分参考了
http://dev.gameres.com/Program/Control/fontDOS.htm  作者吴进

汉字的编码与字模点阵小结相关推荐

  1. 计算机及编码教案,高中信息技术《文字及其处理技术-汉字的编码》教案

    一.教学目标 1.能够说出汉字的编码方式,知道汉字的处理过程. 2.通过阅读教材.小组合作等方法,认识汉字的不同编码,提升分析问题的能力. 3.通过探究计算机处理汉字的过程,消除计算机处理汉字问题的神 ...

  2. delphi 汉字的编码 转换

    delphi 汉字的编码 转换 2009-10-07 21:57:00|  分类: delphi |  标签: |字号大中小 订阅 ━━━━━━━━━━━━━━━━━━━━━━━━━━ var Str ...

  3. JavaScript汉字Unicode编码相互转换

    关键字:JavaScript 汉字转换为Unicode编码 Unicode编码转换为汉字 JavaScript 汉字Unicode编码相互转换代码. JavaScript库 -JavaScript v ...

  4. 汉字编码(【Unicode】 【UTF-8】 【Unicode与UTF-8之间的转换】 【汉字 Unicode 编码范围】【中文标点Unicode码】【GBK编码】【批量获取汉字UNICODE码】)

    参考博客: Unicode与UTF-8互转(C语言实现):http://blog.csdn.net/tge7618291/article/details/7599902 汉字 Unicode 编码范围 ...

  5. 汉字 Unicode 编码范围

    一.汉字Unicode 编码范围 U+ 0 1 2 3 4 5 6 7 8 9 A B C D E F 4e00一丁丂七丄丅丆万丈三上下丌不与丏 4e10丐丑丒专且丕世丗丘丙业丛东丝丞丟 4e20丠両 ...

  6. Unicode对汉字的编码

    1 unicode编码表 Unicode目前普遍采用的是UCS-2,它用两个字节来编码一个字符, 比如汉字"经"的编码是0x7ECF,注意字符编码一般用十六进制来 表示,为了与十进 ...

  7. 计算机应用最普遍的汉字字符编码是什么,计算机中目前最普遍使用的汉字字符编码是什么...

    计算机中目前最普遍使用的汉字字符编码是ASCII码,它是用七位二进制数进行编码的,可表示128个字符.ASCII码是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言. 计算机中目前最 ...

  8. 汉字 Unicode编码范围及 计算文本的中文英文字数

    汉字Unicode编码范围 Unicode编码范围 u4e00~u9fff U+4E00-U+9FA5 是最常用的范围,即名为:CJK Unified Ideographs 的区块, U+9FA6-U ...

  9. Unicode对汉字的编码 1

    1 unicode编码表 Unicode目前普遍采用的是UCS-2,它用两个字节来编码一个字符, 比如汉字"经"的编码是0x7ECF,注意字符编码一般用十六进制来 表示,为了与十进 ...

最新文章

  1. python 打包 .app 运行 控制台窗口_Python打包工具
  2. Myeclipse 10 利用工具生成网络服务接口并调用
  3. RabbitMQ从安装到使用
  4. python itertool_函数式编程的Python实践(2):Itertool
  5. [剑指offer]面试题26:复杂链表的复制
  6. IntelliJ IDEA for Mac在MacOS模式下的搜索/查询/查找快捷键(Search Shortcut)
  7. 我的blog开张了,希望大家能多多赏光啊
  8. android 粘性view_Android自定义StickinessView粘性滑动效果
  9. Linux的iptables常用配置范例(2)
  10. 004-全局应用程序类Global.asax
  11. 一招解决IDEA启动慢的困扰
  12. 设计模式之模板方法模式(Template)
  13. Linux 下删除大量文件效率对比
  14. 网站导航(自定义站点地图)
  15. 成功创业者培养的四个习惯
  16. 面向面试编程-概念之-分布式与集群的区别和联系
  17. 基于视频会议系统的应急指挥项目建设方案
  18. 拉格朗日乘数法怎么判断极大极小_用拉格朗日乘数法求出极值后如何判断其是极大值还是极小值?...
  19. 幼儿园计算机教师论文,幼儿园计算机辅助教学中教师角色定位研究
  20. JSONObject排序问题

热门文章

  1. 手机屏幕投到Windows系统
  2. RPC通信协议远程服务调用(25)Java全栈
  3. (二十三)SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决?
  4. 欢迎大家体验滴滴Logi-KafkaManager
  5. ARMv8/ARMv9的Exclusive机制深度解读
  6. C语言自动出十题四则运算,c语言四则运算出题器
  7. css中的BFC、IFC、GFC、FFC
  8. 【Python web 开发】热销商品 功能实现
  9. 基于热销商品宝贝的数据调用分析
  10. python简单实战项目:《冰与火之歌1-5》角色关系图谱构建