呦呦鹿鸣

  • 一、汉字点阵库使用原理
    • 1.1 汉字编码
      • 1.1.1区位码
      • 1.1.2 机内码
    • 1.2 点阵字库结构
    • 1.3汉字点阵获取
  • 二、实现代码
  • 三、总结
  • 四、参考

一、汉字点阵库使用原理

1.1 汉字编码

1.1.1区位码

  • 在国标 GD2312—80 中规定,所有的国标汉字及符号分配在一个 94 行、94 列的方阵中,方阵的每一行称为一个“区”,编号为 01 区到 94 区,每一列称为一个“位”,编号为01 位到 94 位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯数字就是它们的“区位码”。区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一的
    区位码。汉字“母”字的区位码是 3624,表明它在方阵的 36 区 24 位,问号“?”的区位码为0331,则它在 03 区 3l 位。

1.1.2 机内码

  • 汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上所述,汉字区位码的区码和位码的取值均在 1~ 94 之间,如直接用区位码作为机内码,就会与基本 ASCII 码混淆。为了避免机内码与基本 ASCII 码的冲突,需要避开基本 ASCII 码中的控制码(00H~1FH),还需与基本 ASCII 码中的字符相区别。为了实现这两点,可以先在区码和位码分别加上 20H,在此基础上再加 80H(此处“H”表示前两位数字为十六进制数)。经过这些处理,用机内码表示一个汉字需要占两个字节,分别 称为高位字节和低位字节,这两位字节的机内码按如下规则表示:

高位字节 = 区码 + 20H + 80H(或区码 + A0H)
低位字节 = 位码 + 20H + 80H(或位码 + AOH)

1.2 点阵字库结构

  • 在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0 代表没有,1 代表有点,将 0 和 1 分别用不同颜色画出,就形成了一个汉字。

1.3汉字点阵获取

  • 汉字点阵字库是根据区位码的顺序进行存储的,因此,我们可以根据区位来获取一个字库的点阵,它的计算公式如下:

点阵起始位置 = ((区码- 1)*94 + (位码 – 1)) * 汉字点阵字节数

二、实现代码

  • 这里面用的是2424的汉字库,而ASCII库用的是816的字库,因为用的字库不一样,所以汉字和ASCII码对应的字符需要分别判断,具体的运算思路代码备注里是写了的
#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="tearsgirl.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=18;//要打印的字符长度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();}
  • 结果:

三、总结

  • 利用汉字点阵在图片上打印汉字还是蛮简单的,过程总结一下就是从txt文件里读取数据,然后以16进制存放在数组里,而16进制对应的就是机内码,就可以由此分辨出汉字和字符,也可以通过这个来计算汉字区位码读取字符阵,而opencv的作用就是根据点阵图利用circle函数画实心圆代替像素点来绘字和字符。

四、参考

addtext(汉字叠加代码-函数模块化,非常灵活)-计科1503班-孙西从) (1) (1).cpp(提取码1111)
汉字点阵字库原理 (1).pdf(提取码1111)

图片上打印汉字(C++、OPENCV+字库)相关推荐

  1. Ubuntu下的opencv:在图片上加汉字和数字

    文章内容:本文主要介绍汉字的编码规则,并在ubuntu下调用opencv把汉字和数字叠加在图片上. 一.汉字编码 (一)区位码 在国标 GD2312-80 中规定,所有的国标汉字及符号分配在一个 94 ...

  2. 基于Ubuntu系统调用opencv——在图片上显示汉字和数字

    文章目录 一. 认识汉字编码 (1)区位码 (2)机内码 (3)点阵字库结构 (4)汉字点阵获取 二. 实例--调用opencv在图片上显示文字 (1)准备工作 (2)撰写代码 (3)编译运行 三. ...

  3. 图像处理---《在图片上打印文字 FreeType库》

    图像处理---<在图片上打印文字 FreeType库> 目的:想在处理之后的图像上打印输出结果. 方法: (1)只在图像上打印 数字.字母的话:                 1.Mat ...

  4. python2和python3实现在图片上加汉字

    文章目录 Python2 在图片上加汉字代码实现 Python3 在图片上加汉字代码实现 遇到的问题 python2和python3实现在图片上加汉字,最主要的区别还是内部编码方式不一样导致的,在代码 ...

  5. C++ 在图片上打印文字并保存图片

    int score_record(IplImage* image, string scoreNum, float score ) {CvFont font; //传值给cvPutText()的CvFo ...

  6. 树莓派下利用opencv在图片上画汉字点阵(写一句话)

    一. 点阵字库的原理 一. 汉字编码 1. 区位码 在国标 GD2312-80 中规定,所有的国标汉字及符号分配在一个 94 行.94 列的阵中,方阵的每一行称为一个"区",编号为 ...

  7. python: 在图片上 打印中文

    我整理的代码模板: # 指定字体文件地址 FONT_FILE_PATH = ...# 转换成PIL src_img = cv2.imread(img_path) img_PIL = Image.fro ...

  8. python实现图片上打印文字

    话不多说直接上代码 #先导入所需的包 from PIL import ImageFont, Image, ImageDraw#导入本地字体路径及设置字体大小 font = ImageFont.true ...

  9. php在图片上绘制汉字之imageTtfText()函数

    图片处理,是许多程序的功能之一:而文字渲染则是绘图的基本组成部分.PHP通过很多扩展库来支持图片的处理,最常用的还是GD库,通过一系列imagexxx()函数来提供绘图功能.本文专注于非常细小的一点: ...

  10. php制图汉字,PHP用imageTtfText函数在图片上写入汉字

    PHP绘图,imageString()这个函数并不支持汉字的绘制.这往往会给入门者当头一棒,不过不要着急,因为还有一个imageTtfText()函数,这个函数能绘制UTF-8编码的字符串,当然可以绘 ...

最新文章

  1. 细说反射,Java 和 Android 开发者必须跨越的坎
  2. 8266获取网络时间
  3. CCF大专委2018年大数据发展趋势预测
  4. 算法分析--数量级比较
  5. 模块的封装之C语言类的继承和派生
  6. 无法启动SQL Server 2005中的SQL Serve(MSSQLSERVER)服务
  7. python 文件读写 newline_「Python」:文件读写
  8. CentOS 5.6 使用光驱+系统光盘做YUM源
  9. java序列不存在错误_java.sql.SQLException: ORA-02289: 序列不存在 已解决!
  10. 【学习笔记】n皇后问题的解决方法+改进代码(回溯递归)
  11. codeblocks下载
  12. 如何查看华为android系统,如何查看华为手机系统更新的新增功能
  13. python时间序列进行线性插值_精解Python实现线性插值法——一看就会
  14. python生成复合饼图
  15. mcinabox运行库下载_mcinabox运行库官方版下载_mcinabox运行库 v20200328官方版 - Win7旗舰版...
  16. Pr:速度/持续时间
  17. 微信小程序云开发—校园动物图鉴
  18. 全国 省市区 经纬度 (XML格式)
  19. 双边滤波原理(Bilateral Filtering)
  20. 基于随机森林模型的葡萄酒品质分析

热门文章

  1. Mac电脑音质提示音效调节软件:Boom 3D
  2. 高端存储架构的前世今生
  3. HDS VSP/VM高端存储更换硬盘
  4. 教你们一招免300元直接认证小程序的办法
  5. 巧除Word插入水印后页眉处的折线(转)
  6. AES256加解密java语言实现
  7. 手机下拉框是怎么做出来
  8. 最大堆(创建、删除、插入和堆排序)图文详解
  9. ico 图标 生成 工具 网站
  10. IP.cn - 全国 DNS 服务器 IP 地址汇总 | 公共 DNS 服务器 | DNS 地址