汉字点阵原理字模读取与显示
目录
- 一、汉字点阵字库原理
- (一)汉字编码
- (二)点阵字库结构
- (三)汉字点阵获取
- 二、点阵汉字的字模读取与显示
- 三、总结
- 参考文献
一、汉字点阵字库原理
(一)汉字编码
- 国家标准信息交换用汉字字符集GB 2312-80共收录了汉字、图形符号等共7445个,其中汉字6763个,按照汉字使用的频度分为两级,其中一级汉字3755个,二级汉字3008个。汉字、图形符号根据其位置将其分为94个“区”,每个区包含94个汉字字符,每个汉字字符又称为“位”。其中“区”的序号由01区至94区,“位”的序号也由01位至94位。若以横向表示“位”号,纵向表示“区” 号,则“区”和“位”构成一个二维坐标。给定一个“区”值和“位”值就可以确定一个惟一的汉字或图形符号。即4位阿拉伯数字就可以惟一地确定一个汉字或符号。如“北”字的区位码是“1717”,而京字的区位码是“3009”。前两位是“区”号,后两位是“位”号。其中1至15区是各种图形符号、制表符和一些主要国家的语言字母,16区至87区是汉字,其中16区至55区是一级汉字,56至87区是二级汉字。
- UCDOS软件中的文件HZK16和文件ASC16分别为16×16的国际汉字点阵文件和8×16的ASCII码点阵文件,HZK16中按汉字区位码从小到大依次存放国标区位码表中的所有汉字,每个汉字占用32字节,每个区为94个汉字。而asc16文件中按ascii码从小到大依次存有8×16的ASCII码点阵,每个ASCII码占用16字节。
1.区位码
在国标GB2312—80中规定,所有的国标汉字及符号分配在一个94行、94列的方阵中,方阵的每一行称为一个“区”,编号为01区到94区,每一列称为一个“位”,编号为01位到94位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯数字就是它们的“区位码”。区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一的区位码。汉字“母”字的区位码是3624,表明它在方阵的36区24位,问号“?”的区位码为0331,则它在03区3l位。
2.机内码
汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上所述,汉字区位码的区码和位码的取值均在1-94之间,如直接用区位码作为机内码,就会与基本ASCII码混淆。为了避免机内码与基本ASCII码的冲突,需要避开基本ASCII码中的控制码(00H-1FH),还需与基本ASCII码中的字符相区别。为了实现这两点,可以先在区码和位码分别加上20H,在此基础上再加80H(此处“H”表示前两位数字为十六进制数)。经过这些处理,用机内码表示一个汉字需要占两个字节,分别称为高位字节和低位字节,这两位字节的机内码按如下规则表示:
- 高位字节 = 区码 + 20H + 80H(或区码 + A0H)
- 低位字节 = 位码 + 20H + 80H(或位码 + AOH)
由于汉字的区码与位码的取值范围的十六进制数均为01H-5EH(即十进制的01-94),所以汉字的高位字节与低位字节的取值范围则为A1H-FEH(即十进制的161-254)。例如,汉字“啊”的区位码为1601,区码和位码分别用十六进制表示即为1001H,它的机内码的高位字节为B0H,低位字节为A1H,机内码就是B0A1H。
(二)点阵字库结构
1.点阵字库存储
- 在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0代表没有,1代表有点,将0和1分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有12x12, 14x14, 16x16三种字库。
- 字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期UCDOS字库),纵向矩阵一般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库矩阵做成纵向,省得在显示时还要做矩阵转换。我们接下去所描述的都是指横向矩阵字库。
(三)汉字点阵获取
1.利用区位码获取汉字
汉字点阵字库是根据区位码的顺序进行存储的,因此,我们可以根据区位来获取一个字库的点阵,它的计算公式如下:
- 点阵起始位置 = ((区码- 1)*94 + (位码 – 1)) * 汉字点阵字节数
- 获取点阵起始位置后,我们就可以从这个位置开始,读取出一个汉字的点阵。
2.利用汉字机内码获取汉字
汉字的区位码和机内码的关系
- 机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H)
- 机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH)
也可以根据机内码来获得区位码:
- 区码 = 机内码高位字节 - A0H
- 位码 = 机内码低位字节 - AOH
将这个公式与获取汉字点阵的公式进行合并计就可以得到汉字的点阵位置。
二、点阵汉字的字模读取与显示
在Ubuntu下用C/C++(或python) 调用opencv库编程显示一张图片,并打开一个名为"logo.txt"的文本文件(其中只有一行文本文件,包括你自己的名字和学号),按照名字和学号去读取汉字24*24点阵字形字库(压缩包中的文件HZKf2424.hz)中对应字符的字形数据,将名字和学号叠加显示在此图片右下位置。
创建一个test.cpp
文件写入以下程序
#include<iostream>#include<opencv/cv.h>#include"opencv2/opencv.hpp"#include<opencv/cxcore.h>#include<opencv/highgui.h>#include<math.h>using namespace cv;using namespace std;void paint_chinese(Mat& image,int x_offset,int y_offset,unsigned long offset);void paint_ascii(Mat& image,int x_offset,int y_offset,unsigned long offset);void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path);int main(){String image_path="test.png";char* logo_path="logo1.txt";put_text_to_image(20,300,image_path,logo_path);return 0;}void paint_ascii(Mat& image,int x_offset,int y_offset,unsigned long offset){//绘制的起点坐标Point p;p.x = x_offset;p.y = y_offset;//存放ascii字膜char buff[16]; //打开ascii字库文件FILE *ASCII;if ((ASCII = fopen("Asci0816.zf", "rb")) == NULL){printf("Can't open ascii.zf,Please check the path!");//getch();exit(0);}fseek(ASCII, offset, SEEK_SET);fread(buff, 16, 1, ASCII);int i, j;Point p1 = p;for (i = 0; i<16; i++) //十六个char{p.x = x_offset;for (j = 0; j < 8; j++) //一个char八个bit{p1 = p;if (buff[i] & (0x80 >> j)) /*测试当前位是否为1*/{/*由于原本ascii字膜是8*16的,不够大,所以原本的一个像素点用4个像素点替换,替换后就有16*32个像素点ps:感觉这样写代码多余了,但目前暂时只想到了这种方法*/circle(image, p1, 0, Scalar(0, 0, 255), -1);p1.x++;circle(image, p1, 0, Scalar(0, 0, 255), -1);p1.y++;circle(image, p1, 0, Scalar(0, 0, 255), -1);p1.x--;circle(image, p1, 0, Scalar(0, 0, 255), -1);} p.x+=2; //原来的一个像素点变为四个像素点,所以x和y都应该+2}p.y+=2;}}void paint_chinese(Mat& image,int x_offset,int y_offset,unsigned long offset){//在图片上画汉字Point p;p.x=x_offset;p.y=y_offset;FILE *HZK;char buff[72];//72个字节,用来存放汉字的if((HZK=fopen("HZKf2424.hz","rb"))==NULL){printf("Can't open HZKf2424.hz,Please check the path!");exit(0);//退出}fseek(HZK, offset, SEEK_SET);/*将文件指针移动到偏移量的位置*/fread(buff, 72, 1, HZK);/*从偏移量的位置读取72个字节,每个汉字占72个字节*/bool mat[24][24];//定义一个新的矩阵存放转置后的文字字膜int i,j,k;for (i = 0; i<24; i++) /*24x24点阵汉字,一共有24行*/{for (j = 0; j<3; j++) /*横向有3个字节,循环判断每个字节的*/for (k = 0; k<8; k++) /*每个字节有8位,循环判断每位是否为1*/if (buff[i * 3 + j] & (0x80 >> k)) /*测试当前位是否为1*/{mat[j * 8 + k][i] = true; /*为1的存入新的字膜中*/}else {mat[j * 8 + k][i] = false;}}for (i = 0; i < 24; i++){p.x = x_offset;for (j = 0; j < 24; j++){ if (mat[i][j])circle(image, p, 1, Scalar(255, 0, 0), -1); //写(替换)像素点p.x++; //右移一个像素点}p.y++; //下移一个像素点}
}
void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path){//将汉字弄上图片
//x和y就是第一个字在图片上的起始坐标//通过图片路径获取图片Mat image=imread(image_path);int length=16;//要打印的字符长度unsigned char qh,wh;//定义区号,位号unsigned long offset;//偏移量unsigned char hexcode[30];//用于存放记事本读取的十六进制,记得要用无符号FILE* file_logo;if ((file_logo = fopen(logo_path, "rb")) == NULL){printf("Can't open txtfile,Please check the path!");//getch();exit(0);}fseek(file_logo, 0, SEEK_SET);fread(hexcode, length, 1, file_logo);int x =x_offset,y = y_offset;//x,y:在图片上绘制文字的起始坐标for(int m=0;m<length;){if(hexcode[m]==0x23){break;//读到#号时结束}else if(hexcode[m]>0xaf){qh=hexcode[m]-0xaf;//使用的字库里是以汉字啊开头,而不是以汉字符号开头wh=hexcode[m+1] - 0xa0;//计算位码offset=(94*(qh-1)+(wh-1))*72L;paint_chinese(image,x,y,offset);/*计算在汉字库中的偏移量对于每个汉字,使用24*24的点阵来表示的一行有三个字节,一共24行,所以需要72个字节来表示如赵字区位码是5352十六进制位3534机内码就是d5d4d5-af=38(十进制),因为是从汉字啊开始的,所以减去的是af而不是a0,38+15等于53与区码相对应d4-a0=52*/m=m+2;//一个汉字的机内码占两个字节,x+=24;//一个汉字为24*24个像素点,由于是水平放置,所以是向右移动24个像素点}else{//当读取的字符为ASCII码时wh=hexcode[m];offset=wh*16l;//计算英文字符的偏移量paint_ascii(image,x,y,offset);m++;//英文字符在文件里表示只占一个字节,所以往后移一位就行了x+=16;}}cv::imshow("image", image);cv::waitKey();
}
编译一下
g++ test.cpp -o test `pkg-config --cflags --libs opencv`
显示结果
./test
三、总结
每次实验都会遇到一些不会的问题,想办法去解决它,然后就收获新知识。本次实验需要在Ubuntu里解压rar文件,解决问题过程中也学习了解压命令。做了这次实验也对汉字点阵的原理和结构有了更充分的了解。在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0代表没有,1代表有点,将0和1分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有12x12, 14x14, 16x16三种字库。
参考文献
汉字点阵字库原理
SPI与I2C接口下的OLED显示
ubuntu下如何解压rar文件
汉字点阵原理字模读取与显示相关推荐
- STM32的串口传输文件和点阵汉字的字模读取与显示
文章目录 一.串口传输文件 1.题目要求 2.实验过程 二.汉字点阵原理 1.汉字编码 2.点库字库结构 3.汉字点阵获取 三.Ubuntu下显示图片和文字 1.实验要求 2.实验准备 3.编写代码 ...
- 嵌入式系统基础:点阵汉字的字模读取与显示
点阵汉字的字模读取与显示 虚拟机:VitrualBox 6 系统:Ubuntu 18 函数库:OpenCV 3.4(涉及到图像编程) 文章目录 点阵汉字的字模读取与显示 一.汉字点阵字库原理 1. 汉 ...
- 【嵌入式】在Ubuntu系统下通过OpenCV实现点阵汉字的字模读取与显示
介绍汉字点阵的原理,理解汉字的机内码.区位码编码规则和字形数据存储格式,通过OpenCV在Ubuntu系统下显示点阵汉字 一.汉字点阵原理 1.汉字点阵原理 1.点阵 2.汉字编码 3.点阵字库存储 ...
- Ubuntu下点阵汉字的字模读取与显示
文章目录 一.汉字的区位码.机内码编码规则 1.GB2312标准 2.区位码 3.机内码 二.字形数据存储格式 1. Unicode 字符集和编码 2.字模 3.汉字点阵获取 三.在图片上叠加显示学号 ...
- Ubuntu下利用Opencv进行点阵汉字的字模读取与显示
前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容. 提示:以下是本篇文章正文内容, ...
- 虚拟机下点阵汉字的字模读取与显示
目录 一.汉子点阵字库原理 二.实验 三.总结 四.参考 一.汉子点阵字库原理 (1) 汉字编码 1. 区位码 在国标 GD2312-80 中规定,所有的国标汉字及符号分配在一个 94 行.94 列 ...
- pc机之间的通信和点阵汉字的字模读取与显示
pc机之间的通信 连线设置 点阵汉字的读取与打印 在ubuntu下面用c调用opencv显示文字和图片 总结 连线设置 两个usb转换口 G-G,3.3-3.3,TX-RX,RX-TX 打开串口助手选 ...
- c语言16x32点阵显示汉字,点阵16*32滚屏显示汉字
// matrix2pcs20140821.ino const int SH_CP = 8; const int DS = 9; const int ST_CP = 10; //声明4个数组临时变量 ...
- 借助USB转RS232 模块串口传输练习、基于Ubuntu调用Opencv的点阵汉字字模读取
借助USB转RS232 模块串口传输练习.基于Ubuntu调用Opencv的点阵汉字字模读取 文章目录 借助USB转RS232 模块串口传输练习.基于Ubuntu调用Opencv的点阵汉字字模读取 1 ...
最新文章
- windows 7 下安装 Android 设备驱动
- MFC指定位置画位图
- Highmaps网页图表教程之数据标签与标签文本
- Android]Android字体高度的研究
- Laravel测试驱动开发--反向单元测试
- 小学阅读方法六种_小学数学速算六种方法
- ES(elasticsearch)备份还原脚本
- 数据包络分析例题解析(含MATLAB代码)
- 正交设计 python算法_正交设计 - SegmentFault 思否
- .net core 创建桌面应用程序(极简流程)
- Scratch中设置物体的中心点
- 解决Win10下安装office2013问题
- 二叉平衡树的算法复杂度笔记
- 两年工作经验的后端开发的工作方法小结
- 大白菜读取linux硬盘,大白菜的linux之旅,文件操作首探
- 译码器设计——Verilog HDL语言
- 【20210903】【实践分享】架构师岗位的一次面试
- 锐取录播服务器咋样进系统界面,锐取录播系统
- 游戏角色跟场景建模那个好一点?
- keepass2android 远程,关于KeePass实现mstsc远程桌面(rdp协议)的自动登录
热门文章
- Arcgis创建新色带
- 移动端图片单指移动,双指放大缩小实现//touchmove的时候不让body滚动
- 如何改变图片的大小kb
- rockchip研讨会_地下在线研讨会6
- 网易云音乐插件v2.8.2 安卓版
- 数据结构与算法实验 实验6:二叉树ADT的二叉链式实现 (由完全前序序列创建二叉树 / 求二叉树的节点数/树高/叶子节点数 /先序中序后序层序遍历)
- 2021营销案例盘点,这些品牌的中秋营销创意,绝了!
- dede服务器建站_织梦教程,网站搭建,网站成功部署教程
- 一碗牛肉面的成本是多少钱?
- python访问陌生人qq空间_在Python中使用Phantomjs模拟登录QQ空间