Font reading and display of dot matrix Chinese characters

Keywords: OpenCV

1, Chinese character dot matrix library

1. Chinese character coding

1.1 location code

  1. It is stipulated in the national standard GD2312-80 that all national standard Chinese characters and symbols are allocated in a square matrix with 94 rows and 94 columns
  2. Each row of the square array is called a "zone"
  3. Each column is called a "bit"
  4. The area code and tag number of each Chinese character and symbol in the array are combined to form four Arabic numerals, which are their "location code".
  5. The first two digits of the location code are its area code and the last two digits are its bit code.
  6. A Chinese character or symbol can be uniquely determined by location code. Conversely, any Chinese character or symbol also corresponds to a unique location code.

1.2 internal code

High byte = area code + 20h + 80h (or area code + A0H)
Low byte = bit code + 20h + 80h (or bit code + AOH)

  1. The internal code of Chinese characters refers to the code that represents a Chinese character in the computer.
  2. First add 20H to the area code and bit code respectively, and then add 80h on this basis (here "H" means that the first two digits are hexadecimal
    Number).

2. Lattice font structure

  • In the dot matrix font of Chinese characters, each bit of each byte represents a point of a Chinese character. Each Chinese character is composed of a rectangular dot matrix, 0 represents no, 1 represents a point. Draw 0 and 1 in different colors to form a Chinese character.
  • The font is divided into horizontal matrix and vertical matrix according to the different points represented by bytes. In order to improve the display speed, the font matrix is made into vertical matrix
  • Commonly used lattice matrices are 12 ∗ 12 12*12 12∗12, 14 ∗ 14 14*14 14∗14, 16 ∗ 16 16*16 16 * 16 three word libraries

3. Chinese character dot matrix acquisition

3.1 location code acquisition

Lattice start position = ((area code - 1) * 94 + (bit code - 1)) * number of Chinese character lattice bytes

3.2 acquiring Chinese characters by Chinese character internal code

High byte of internal code = area code + 20h + 80h (or area code + A0H)
Low byte of internal code = bit code + 20h + 80h (or bit code + AOH)

Area code = high byte of internal code - A0H
Bit code = low byte of internal code - AOH

2, Chinese character display

Program code:

#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){
    //Coordinates of the starting point of the drawing
	Point p;
	p.x = x_offset;
	p.y = y_offset;
	 //Storing ascii word film
	char buff[16];           
	//Open ascii font file
	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++)                  //Sixteen char s
	{
		p.x = x_offset;
		for (j = 0; j < 8; j++)              //One char and eight bit s
		{
			p1 = p;
			if (buff[i] & (0x80 >> j))    /*Test whether the current bit is 1*/
			{
				/*
					Because the original ascii word film was 8 * 16, it was not large enough,
					So the original pixel is replaced by four pixels,
					After replacement, there are 16 * 32 pixels
					ps: I think it's unnecessary to write code like this, but I only think of this method for the time being
				*/
				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;            //One pixel becomes four, so x and y should both be + 2
		}
		p.y+=2;
	}
}
void paint_chinese(Mat& image,int x_offset,int y_offset,unsigned long offset){//Draw Chinese characters on the picture
    Point p;
    p.x=x_offset;
    p.y=y_offset;
    FILE *HZK;
    char buff[72];//72 bytes for storing Chinese characters

    if((HZK=fopen("HZKf2424.hz","rb"))==NULL){
        printf("Can't open HZKf2424.hz,Please check the path!");
        exit(0);//sign out
    }
    fseek(HZK, offset, SEEK_SET);/*Move the file pointer to the offset position*/
    fread(buff, 72, 1, HZK);/*Read 72 bytes from the offset position, and each Chinese character occupies 72 bytes*/
    bool mat[24][24];//Define a new matrix to store the transposed text film
    int i,j,k;
    for (i = 0; i<24; i++)                 /*24x24 Dot matrix Chinese characters, a total of 24 lines*/
	{
        	for (j = 0; j<3; j++)                /*There are 3 bytes in the horizontal direction, and the value of each byte is determined by cycle*/
			for (k = 0; k<8; k++)              /*Each byte has 8 bits, and the loop judges whether each byte is 1*/
				if (buff[i * 3 + j] & (0x80 >> k))    /*Test whether the current bit is 1*/
				{
					mat[j * 8 + k][i] = true;          /*1 is stored in a new word film*/
				}
				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);		  //Write (replace) pixels
			p.x++;                                                //Shift right one pixel
		}
		p.y++;                                                    //Move down one pixel
	}
}

void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path){//Put Chinese characters on the picture
//x and y are the starting coordinates of the first word on the picture
    //Get pictures through picture path
    Mat image=imread(image_path);
    int length=18;//Length of characters to print
    unsigned char qh,wh;//Define area code and tag number
    unsigned long offset;//Offset
    unsigned char hexcode[30];//Hexadecimal used to store Notepad reading. Remember to use unsigned
    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: the starting coordinate of the text drawn on the picture

    for(int m=0;m<length;){
        if(hexcode[m]==0x23){
            break;//It ends when the # number is read
        }
        else if(hexcode[m]>0xaf){
            qh=hexcode[m]-0xaf;//The font used starts with Chinese characters, not Chinese symbols
            wh=hexcode[m+1] - 0xa0;//Calculation bit code
            offset=(94*(qh-1)+(wh-1))*72L;
            paint_chinese(image,x,y,offset);
            /*
            Calculate the offset in the Chinese character library
            Each Chinese character is represented by a 24 * 24 dot matrix
            A line has three bytes, a total of 24 lines, so 72 bytes are required
            */

            m=m+2;//The internal code of a Chinese character occupies two bytes,
            x+=24;//A Chinese character has 24 * 24 pixels. Because it is placed horizontally, it moves 24 pixels to the right
        }

        else{
        //When the read character is ASCII
        wh=hexcode[m];
        offset=wh*16l;//Calculate the offset of English characters
        paint_ascii(image,x,y,offset);
        m++;//English characters only occupy one byte in the file, so just move back one bit
        x+=16;
        }

    }

    cv::imshow("image", image);
    cv::waitKey();
}

Implemented with VMWare+OpenCV
Before use, you can query bytecode through UltraEdit

  1. File - > open file - > logo.txt file
  2. Edit - > hex function - > hex edit
    • x20 represents a space
    • ASCII after x20 🐎 The number of is 0x3x, indicating that the number is the student number bit
    • The first six bytes represent different Chinese characters 0xcd and 0xf5 represent a Chinese character internal code
  3. After the query, the later pictures and Chinese characters are superimposed, and the logo.txt file is written in ANSI code
  4. Download the necessary software packages in OpenCV and decompress them
    • You need to call the HZKf2424.hz file and unzip the file into the same file directory to facilitate file calling
    • Create a new test.cpp file and logo1.txt file, and store them in the same directory as the call file
  5. Run the program, open the terminal in the directory, and run the c + + command
g++ test.cpp -o test3 `pkg-config --cflags --libs opencv`


6. Compile the file and run the file

./test3

7. Operation results

3, Summary

  • Using Chinese character dot matrix to print text on the picture is to read the data in txt file, and then store the transposed hexadecimal data in the array (internal code)
  • OpenCV uses the Circle function to draw solid points and draws characters according to the dot matrix instead of pixels

4, Reference

(Chinese character superposition code - function modularization, very flexible) - Jike class 1503 - Sun Xicong
Print Chinese characters on the picture (C + +, OPENCV + font library)
C + + superimposes Chinese characters on pictures

Posted by quizzical on Fri, 05 Nov 2021 13:49:39 -0700