目录

一.汉字点阵字库原理

1.汉字编码

1.1区位码

1.2机内码

2.点阵字库结构

点阵字库存储

3 汉字点阵获取

二、Ubuntu+Opencv+C++显示图片

1.将图片、Asci0816.zf和HZKf2424.hz放到文件夹中

2.创建test3.cpp文件,并将实现代码写入

3.创建logo.txt文件,并写入图片上显示的文字内容

4.编译

5.运行

6.结果

一.汉字点阵字库原理

1.汉字编码

1.1区位码

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

1.2机内码

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

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

2.点阵字库结构

点阵字库存储

在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉 字都是由一个矩形的点阵组成,0 代表没有,1 代表有点,将 0 和 1 分别用不同 颜色画出,就形成了一个汉字,常用的点阵矩阵有 1212, 1414, 16*16 三 种字库。 字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库 都是横向矩阵的存储方式(用得最多的应该是早期 UCDOS 字库),纵向矩阵一 般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库 矩阵做成纵向,省得在显示时还要做矩阵转换。我们接下去所描述的都是指横向 矩阵字库。

3 汉字点阵获取

  • 汉字点阵字库是根据区位码的顺序进行存储的,因此,我们可以根据区位来获取一个字库的点阵,它的计算公式如下:点阵起始位置 = ((区码- 1)*94 + (位码 – 1)) * 汉字点阵字节数

二、Ubuntu+Opencv+C++显示图片

1.将图片、Asci0816.zf和HZKf2424.hz放到文件夹中

实现代码(需要自己更改路径)

#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="/home/x-huxi/myhomework/chinesetest/yousee.png";char* logo_path=(char*)"/home/x-huxi/myhomework/chinesetest/logo.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("/home/x-huxi/myhomework/chinesetest/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("/home/x-huxi/myhomework/chinesetest/HZKs2424.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();}

2.创建test3.cpp文件,并将实现代码写入

vim test3.cpp

3.创建logo.txt文件,并写入图片上显示的文字内容

vim logo.txt

输入代码后按Esc键输入:wq保存退出

注:txt文件不能采用UTF-8编码,否则图片中的文字会出现乱码。要使用ANSI编码。

4.编译

g++ test3.cpp -o test3 `pkg-config --cflags --libs opencv`

5.运行

./test3

6.结果

总结:

前面的步骤一直很顺利,没仔细看txt文本默认的是UTF-8,导致图片中的文字出现乱码,在这里卡了很久。仔细了解才知道是txt文件编码导致的问题,只要更改为ANSI编码图片中的文字就能正常显示。

参考:

(37条消息) 点阵汉字的字模读取与显示_一只特立独行的猪 ️的博客-CSDN博客

Ubuntu+OpenCV学习汉字点阵,图片打印汉字相关推荐

  1. Ubuntu+OpenCV学习汉字点阵

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

  2. openCV学习笔记1——图片的读取,显示,保存;视频的读取,显示和保存

    在pycharm中下载openCV ①打开pycharm下方的terminal终端 ②在路径下直接输入 pip install opencv-python 1.读入图像 函数:cv2.imread() ...

  3. OpenCV学习五:图片矩形区域的读取

    #include <opencv2/opencv.hpp> #include <stdio.h> #include <stdlib.h>using namespac ...

  4. Mastering Opencv学习笔记(1)——图片卡通化

    一.简介 可以通过opencv将图片进行卡通化处理,基本的思路是将图片的内容部分进行平滑处理,然后让边缘部分更加突出.首先,通过边缘检测滤波器获得图像的黑白素描图,然后通过双边滤波器获得平滑后的图像, ...

  5. OLED屏显和汉字点阵编码

    目录 一.SPI协议 (1)SPI协议简介 (2)SPI物理层 (3)协议层 (4)SPI 基本通讯过程 (5)CPOL/CPHA 及通讯模式 (6)通讯引脚 (7)SPI优缺点 二.OLED (1) ...

  6. Ubuntu 下调用 opencv 在图片显示汉字和数字

    目录 实验要求: 1 环境准备 1.1创建文件 实验要求: 学习理解汉字的机内码.区位码编码规则和字形数据存储格式.在Ubuntu下用C/C++(或python) 调用opencv库编程显示一张图片, ...

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

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

  8. python+opencv+PIL,在图片和视频中写入中文(汉字)

    原博客地址:https://blog.csdn.net/wyx100/article/details/80412101 效果 代码 #!/usr/bin/env python # -*- coding ...

  9. 汉字点阵原理字模读取与显示

    目录 一.汉字点阵字库原理 (一)汉字编码 (二)点阵字库结构 (三)汉字点阵获取 二.点阵汉字的字模读取与显示 三.总结 参考文献 一.汉字点阵字库原理 (一)汉字编码 国家标准信息交换用汉字字符集 ...

  10. 在Ubuntu调用opencv库编程显示图片并叠加文字

    一.汉字编码介绍 (一)区位码 (二)机内码 (三)点阵字库储存 (四)汉字点阵获取 二.操作步骤 (一)操作环境 OpenCV (二)实验准备 (1)下载中文点阵字库及显示工具程序 (2)将所需文件 ...

最新文章

  1. DirectX 开发环境配置
  2. JAVA JDK+Eclipse IDE for Java Developers下载
  3. 每天学习一点,坚持学习!!
  4. Android UI控件----ExpandableListView的基本用法
  5. win10专业版占多少空间_win10技巧:使用win10轻松自动恢复系统!
  6. acrgis api for javaScript中的portal查询
  7. 四.开发记录之ubuntu系统安装ROS和开发环境
  8. java 输入密码时显示星号6_Java多线程 例子 cmd窗口下 实现输入密码星号显示
  9. 实战篇:如何建设企业的营销管理和分析平台
  10. Linux读写I2C设备I2C_RDWR用法
  11. linux服务器知识学习:了解Linux系统的启动过程
  12. Winform 调整SplitContainer中Panel的大小
  13. javascript实现根据汉字获取拼音或者获取拼音首字母
  14. notion函数_最适合设计师的笔记软件 Notion
  15. python计算工资一周不超过40小时_GitHub - xk1411/Python-100-Days: Python - 100天从新手到大师...
  16. 微信加菲猫连接服务器失败,加菲猫微信表情包
  17. 荣耀变局之下,国产智能手机九年往事
  18. 三菱fx2n plc用什么编程软件
  19. 【考研总结】考研失败后的反省
  20. 视频教程-软考系统集成项目管理工程师视频教程(上)-软考

热门文章

  1. Qt 如何获取本机ip地址
  2. 免备案去掉端口号访问网站
  3. matlab 矩阵最大值的求法
  4. pandas to_excel产生空值的解决方案
  5. 微信支付的appid,appsecret,商户号mchid,微信交易支付密钥在哪里查看
  6. c语言判断二次函数,知识:六法搞定二次函数解析式的确定
  7. 加密流量分类任务的深度学习方法(一般框架总结)
  8. 在张朝阳的直播间里,没有搜狐的未来
  9. 终于,连字节、腾讯都烧不起钱了
  10. 极路由2刷机为openwrt固件