Ubuntu系统要安装好编译环境,若无,详情参考:https://blog.csdn.net/arau_sh/article/details/6587396
目录- 一、区位码与机内码简介
- 二、字形数据存储与获取
- 三、Ubuntu下展示
- 3.1 ubuntu新建文件夹
- 3.2 代码及.txt文件
- 3.3 运行结果
- 四、总结
一、区位码与机内码简介
- 所有汉字及符号放在一个94*94的方阵中,行叫做区,列叫做位,所以是94区、94位,也可以理解为坐标,每一个汉字或者符号都对应一个区码和位码,把区码和位码组合起来,区码在前,位码在后,就是区位码。
GB2312字符集中:
1)01~09区(682个):特殊符号、数字、英文字符、制表符等,包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母等在内的682个全角字符;
2)10~15区:空区,留待扩展;
3)16~55区(3755个):常用汉字(也称一级汉字),按拼音排序;
4)56~87区(3008个):非常用汉字(也称二级汉字),按部首/笔画排序;
5)88~94区:空区,留待扩展
- 在计算机中,区位码会与ASCII码混淆,为了避免混淆,要避开ASCII码(00H~1FH),还要与ASCII码相区分开,所以在原始的区码和位码上分别加上20H(避开ASCII码),加上80H,分别构成高位字节和低位字节。
- 80H原因:规定国标码中的每个字节的最高位都从0换成1,即相当于每个字节都再加上128(十六进制为80,即80H;二进制为1000 0000),由于ASCII码只用了一个字节中的低7位,所以,这个首位(最高位)上的“1”就可以作为识别汉字编码的标志,计算机在处理到首位是“1”的编码时就把它理解为汉字,在处理到首位是“0”的编码时就把它理解为ASCII字符。
- 点阵存储
- 获取汉字方式
3.2 代码及.txt文件新建一个文件夹,将所用图片,.cpp代码,.txt文件,ASCII码,24*24汉字点阵文件都放在这个文件夹中。
- 编译1.cpp程序
#include#include #include"opencv2/opencv.hpp" #include #include #include 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="1.jpeg"; char* logo_path="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("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)) { 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); bool mat[24][24];//定义一个新的矩阵存放转置后的文字字膜 int i,j,k; for (i = 0; i<24; i++) { for (j = 0; j<3; j++) for (k = 0; k<8; k++) if (buff[i * 3 + j] & (0x80 >> k)) { mat[j * 8 + k][i] = true; } 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 0xaf){ qh=hexcode[m]-0xaf;//使用的字库里是以汉字啊开头,而不是以汉字符号开头 wh=hexcode[m+1] - 0xa0;//计算位码 offset=(94*(qh-1)+(wh-1))*72L; paint_chinese(image,x,y,offset); 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时字符编码注意保存为简体中文,否则会乱码。
- 乱码结果
- 编译.cpp程序
g++ 1.cpp `pkg-config --cflags --libs opencv` -o 1
./1执行程序
细节很重要,编译语句小错误会犯。
参考文章:
https://www.cnblogs.com/benbenalin/p/6907907.html
https://blog.csdn.net/junseven164/article/details/121130735



