Font-type display of dot-matrix Chinese characters on Linux

Keywords: Linux

I Chinese Character Dot Matrix Font Library

Code

Location Code
_In the national standard GD2312-80, all Chinese characters and symbols are assigned to a square array of 94 rows and 94 columns. Each row of the square array is called a "zone", numbered from 01 to 94, and each column is called a "bit", numbered from 01 to 94. The four Arabic numerals formed by the combination of the area code and digit number in which each Chinese character and symbol reside in the square matrix are their "area code".
The first two bits of an area code are its area code, and the last two are its bit number. A Chinese character or symbol can be uniquely identified by a region code. Conversely, any Chinese character or symbol corresponds to a unique region code. The area code of the Chinese character Alphabet is 3624, indicating that it is 24 in block 36 of the square array and 0331 for the question mark'?', then it is 31 in block 03.
machine code
_The internal code of a Chinese character refers to the encoding that represents a Chinese character in a computer. The internal code is slightly different from the area code. As mentioned above, both the area code and the bit code of the Chinese character area code are between 1 and 94. If the area code is used directly as the internal code, it will be confused with the basic ASCII code. To avoid the conflict between the internal code and the basic ASCII code, you need to avoid the control code (00H~1FH) in the basic ASCII code and distinguish the characters from the basic ASCII code. To achieve these two points, add 20H to the code and 80H to the bitcode (where "H" means the first two digits are hexadecimal). After these processes, it takes up two bytes to represent a Chinese character with the internal code, which is called high-bit byte and low-bit byte, respectively. The internal code of these two bytes is represented by the following rules:

High-bit bytes = area code + 20H + 80H (or area code + A0H)
Low-bit bytes = bitcode + 20H + 80H (or bitcode + AOH)

Lattice acquisition

Area Code=Internal Code High Bit Bytes-A0H
Bit = Internal Code Low Bit Bytes - AOH

Dot matrix starting position = ((area code-1)*94 + (bitcode-1)*Chinese character dot matrix bytes

II Ubuntu Use C++ Call OpenCV to Overlay Chinese Characters on Pictures

1. Code preparation

Prepare picture, 24 dot matrix.hz file, ASCII code.zf file, logo, main

Write in main.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="./gou.png";
    char* logo_path=(char*)"./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){

    //Starting point coordinates of the drawing
	Point p;
	p.x = x_offset;
	p.y = y_offset;
	 //Store ascii membranes
	char buff[16];           
	//Open ascii font library 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 eight bit s
		{

			p1 = p;
			if (buff[i] & (0x80 >> j))    /*Test if the current bit is 1*/
			{
			
				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;            //The original pixel point 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 pictures
    Point p;
    p.x=x_offset;
    p.y=y_offset;
    FILE *HZK;
    char buff[72];//72 bytes for storing Chinese characters
    if((HZK=fopen("./HZKs2424.hz","rb"))==NULL){

        printf("Can't open HZKf2424.hz,Please check the path!");
        exit(0);//Sign out
    }

    fseek(HZK, offset, SEEK_SET);/*Move file pointer to offset position*/
    fread(buff, 72, 1, HZK);/*Read 72 bytes from offset position, 72 bytes per Chinese character*/
    bool mat[24][24];//Define a new matrix to store transposed text membranes
    int i,j,k;
    for (i = 0; i<24; i++)                 /*24x24 Dotted Chinese characters, a total of 24 lines*/
	{
		for (j = 0; j<3; j++)                /*There are 3 bytes horizontally, and the loop judges each byte's*/
			for (k = 0; k<8; k++)              /*8 bits per byte, loop to determine if each bit is 1*/
				if (buff[i * 3 + j] & (0x80 >> k))    /*Test if the current bit is 1*/
				{
					mat[j * 8 + k][i] = true;          /*Store 1 in a new membrane*/

				}
				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) pixel points
			p.x++;                                                //Move one pixel to the right
		}
		p.y++;                                                    //Move down a pixel point
	}
}



void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path){
//Make pictures of Chinese characters
//x and y are the starting coordinates of the first word on the picture
    //Get Pictures from Picture Path

    Mat image=imread(image_path);
    int length=18;//Length of characters to print
    unsigned char qh,wh;//Define area code, bit number
    unsigned long offset;//Offset
    unsigned char hexcode[30];//Hexadecimal for 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: Starting coordinates for drawing text on a picture
    for(int m=0;m<length;){
        if(hexcode[m]==0x23){
            break;//End when #is read
        }
        else if(hexcode[m]>0xaf){
            qh=hexcode[m]-0xaf;//Use a font library that starts with a Chinese character, not a Chinese character symbol
            wh=hexcode[m+1] - 0xa0;//Compute Bit Codes
            offset=(94*(qh-1)+(wh-1))*72L;
            paint_chinese(image,x,y,offset);

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

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

    }

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

2. Compile

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

3. Results



Success

Summary

Installing opencv in Ubuntu has encountered many problems as follows Blog Solve, understand the internal code of Chinese characters, encoding rules of area code and glyph data storage format, and use opencv to cover Chinese characters on pictures.

link
Download Installation and Environment Configuration of OpenCV under Ubuntu 20.04

Posted by weekenthe9 on Fri, 12 Nov 2021 11:58:38 -0800