Python 用点阵字库描绘出国庆祝福语:祝福伟大祖国,更加繁荣昌盛 我爱你,中国

简介: Python 用点阵字库描绘出国庆祝福语:祝福伟大祖国,更加繁荣昌盛 我爱你,中国

在给网友答题时突然间想到的,要把点阵字库拿出来研究研究的。适逢国庆佳节,刚好用它来打印国庆节祝福语,以表达我对伟大祖国生日的致敬!




❤️一段老代码


以下是一段上世纪90年代比较流行的C代码,从字库文件里读取字模然后还原成点阵输出:

#include <stdio.h>
#include <conio.h>
const unsigned char bit[8]={128,64,32,16,8,4,2,1};
unsigned char buffer[32];
unsigned long offset;
unsigned int q,w;
int x,y,qw;
void display(char *hz) {
    FILE *hzk;
    qw = *((int *)hz);
    q = (qw&0x00FF)-0xA1;
    w = ((qw>>8)&0x00FF)-0xA1;
    offset = q*0x5E + w;
    offset *= 32;
    if ((hzk = fopen("HZK16","rb"))==NULL) {
        printf("Can not open file HZK16!\n");
        return;
    }
    fseek(hzk,offset,SEEK_SET);
    fread(buffer,1,32,hzk);
    fclose(hzk);
    for (y=0;y<16;y++) {
      printf("  ");
        for (x=0;x<16;x++) {
            if (buffer[y*2+x/8] & bit[x%8]) {
                printf("%s","*");
            } else {
                printf("  ");
            }
        }
        printf("\n");
    }
    printf("\n");
}
int main() {
    display("国"); display("庆"); display("节");
    getch();
}



以上代码在 Dev-C++ 5.11(TDM-GCC 4.9.2 64-bit) 上通过编译,效果如下:

1776141dde9848aeb6723578d00effff.png

实际输出时字是竖排的,为降低图片高度已ps成横排  




❤️点阵字库原理


点阵字库是比较古老的技术,上世纪90年代初个人PC刚刚出现,中文大多都是用点阵字库来记录的,读出汉字字模后用于显示和打印,有12点阵、16点阵、24点阵以及32点阵等。1992年时,我见到了当时学校唯一一台486的康柏电脑,安装的是Win3.1中文版,也是我第一次见到有图形界面的操作系统。后来很多年后才由现在广泛使用的矢量字库逐渐替代点阵字库,不过现在还有银行等单位在用针式打印机打印凭证、报表等,里面固化的应该还是点阵字库。


   以下原理性表述来源于网络:


   HZK16字库是符合GB2312标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中一级汉字有 3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。HZK16字库里的16×16汉字一共需要256个点来显示,也就是说需要32个字节才能达到显示一个普通汉字的目的。


   一个GB2312汉字是由两个字节编码的,范围为0xA1A1~0xFEFE。A1-A9为符号区,B0-F7为汉字区。每一个区有94个字符(注意:这只是编码的许可范围,不一定都有字型对应,比如符号区就有很多编码空白区域)。


   下面以汉字"我"为例,介绍如何在HZK16文件中找到它对应的32个字节的字模数据。前面说到一个汉字占两个字节,这两个中前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的位置。所以要找到"我"在hzk16库中的位置就必须得到它的区码和位码。


   区码: 汉字的第一个字节-0xA0  

   位码: 汉字的第二个字节-0xA0


   汉字编码是从0xA0区开始的, 所以文件最前面就是从0xA0区开始, 要算出相对区码。这样就可以得到汉字在HZK16中的绝对偏移位置: offset=(94*(区码-1)+(位码-1))*32


   注解:


   区码减1是因为数组是以0为开始而区号位号是以1为开始的

   (94*(区号-1)+位号-1)是一个汉字字模占用的字节数

   最后乘以32是因为一个汉字要用到32个字节来存储。


注:在上面C代码中所用到的及以下python代码中将会用到的,就是上述文字中所讲到的字体文件“HZK16”,可以到网上搜索“UCDOS HZK16下载”来获得。




❤️改写C代码


实现用python显示点阵字库

def hzk_offset(hz):
    q,w = list(bytes(hz,encoding='gbk'))
    return ((q-161)*94+w-161)*32
def hz_buffer(hzstr):
    buffers = []
    f = open('d:\\hzk16','rb')
    for z in hzstr:
        f.seek(hzk_offset(z),0)
        buffers.append(f.read(32))
    f.close()
    return buffers
def hz_print(hzstr):
    buffers = hz_buffer(hzstr)
    bit = [2**i for i in range(7,-1,-1)]
    for buffer in buffers:
        for y in range(16):
            for x in range(16):
                if buffer[y*2+x//8]&bit[x%8]:
                    print(".",end='\n' if x==15 else '')
                else:
                    print(' ',end='\n' if x==15 else '')
        print()
if __name__ == '__main__':
    hz_print('国庆快乐')



上述代码运行的效果为下图左一,中间和右边的效果只要把 hz_print() 函数中第一句print()输出字符串分别改为"★"和“***”,第二句print()输出字符串分别改2个和3个空格。

4fc8feade49746e8998b027adc8819b3.png




❤️改进python代码


把文字竖排输出改进成横排输出,重点是重组字模数组的顺序:

fccb517ed4744d1fa201b63c0b4c76c5.png



代码如下:

def hzk_offset(hz):
    q,w = list(bytes(hz,encoding='gbk'))
    return ((q-161)*94+w-161)*32
def hz_buffer(hzstr):
    buffers = []
    f = open('d:\\hzk16','rb')
    for z in hzstr:
        f.seek(hzk_offset(z),0)
        buffers.append(list(f.read(32)))
    f.close()
    return buffers
def hz_print(hzstr):
    global tmp
    buffers = hz_buffer(hzstr)
    bit = [2**i for i in range(7,-1,-1)]
    tmp = ['']*16
    for n,buffer in enumerate(buffers):
        for y in range(16):
            for x in range(16):
                if buffer[y*2+x//8]&bit[x%8]:
                    tmp[y] += '*'
                else:
                    tmp[y] += ' '
    for t in tmp: print(t)
if __name__ == '__main__':
    print()
    hz_print('祝福伟大祖国')
    print()
    hz_print('更加繁荣昌盛')
    print()
    hz_print('我爱你,中国!')
    print()



由于控制台的输出的文字间隔比较大,所以显得有点粗壮。如果把这些点阵信息还原到图形界面中去,就可以缩小间隔显示成很小的字;甚至可以读取32点阵字库,这样文字会显得更圆润饱满。


e37c8adc7a4a4d5bb37378b88f808d8d.png


源代码如下:

import pygame,sys
from pygame import *
WIDTH,HEIGHT = 640,480
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)
def hzk_offset(hz):
    q,w = list(bytes(hz,encoding='gbk'))
    return ((q-161)*94+w-161)*32
def hz_buffer(hzstr):
    buffers = []
    f = open('d:\\hzk16','rb')
    for z in hzstr:
        f.seek(hzk_offset(z),0)
        buffers.append(list(f.read(32)))
    f.close()
    return buffers
def hz_matrix(hzstr,BOLD=0):
    global tmp
    buffers = hz_buffer(hzstr)
    bit = [2**i for i in range(7,-1,-1)]
    tmp = ['']*16
    if BOLD==0:
        str = '1','0'
    else:
        str = '11','00'
    for n,buffer in enumerate(buffers):
        for y in range(16):
            for x in range(16):
                if buffer[y*2+x//8]&bit[x%8]:
                    tmp[y] += str[0]
                else:
                    tmp[y] += str[1]
    return tmp
def draw_hz(hzstr,x,y,d=1,color=BLACK,BOLD=0):
    matrix = hz_matrix(hzstr,BOLD)
    for j,mat in enumerate(matrix):
        for i,dot in enumerate(list(mat)):
            if dot=='1':
                pos_on_screen, radius = (x+i*d, y+j*d), d
                draw.circle(screen, color, pos_on_screen, radius)
if __name__ == '__main__':
    pygame.init()
    screen = display.set_mode((WIDTH,HEIGHT),0,32)
    display.set_caption("祝大家国庆节快乐!")
    screen.fill(WHITE)
    timer = pygame.time.Clock()
    draw_hz('祝福伟大祖国',  80,30)
    draw_hz('更加繁荣昌盛',  80,50)
    draw_hz('我爱你,中国!',80,70)
    draw_hz('祝福伟大祖国',  80,120,2,RED)
    draw_hz('更加繁荣昌盛',  80,160,2,RED)
    draw_hz('我爱你,中国!',80,200,2,RED)
    draw_hz('祝福伟大祖国',  80,280,2,RED,1)
    draw_hz('更加繁荣昌盛',  80,330,2,RED,1)
    draw_hz('我爱你,中国!',80,380,2,RED,1)
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
        timer.tick(60)
        display.update()

热烈庆祝中华人民共和国成立72周年!



目录
相关文章
|
8月前
|
前端开发 测试技术 Linux
芯片人的快乐——python+systemverilog用波形祝你新春快乐 |献上祝福语波形生成器|
芯片人的快乐——python+systemverilog用波形祝你新春快乐 |献上祝福语波形生成器|
|
1月前
|
Python
python烟花绘制,春节祝福
python烟花绘制,春节祝福
27 0
|
9月前
|
开发者 Python
用 Python 将 QQ 好友头像生成祝福语
用 Python 将 QQ 好友头像生成祝福语
31 0
用 Python 将 QQ 好友头像生成祝福语
|
9月前
|
编解码 Python
Python3,我把新年祝福写在“雨“中,你看,雨一直下,气氛还算融洽,在同个屋檐下....
Python3,我把新年祝福写在“雨“中,你看,雨一直下,气氛还算融洽,在同个屋檐下....
45 0
|
11月前
|
机器学习/深度学习 计算机视觉 Python
用Python写一份独特的元宵节祝福
首先是点阵字的概念:点阵字体是把每一个字符都分成 n * n 个点,然后用每个点的虚实来表示字符的轮廓。点阵字体也叫位图字体,其中每个字形都以一组二维像素信息表示。
|
编解码 安全 Python
Python3,我把新年祝福写在“雨“中,雨一直下,气氛还算融洽...
我再也不羡慕 好莱坞电影中黑客电脑的屏幕了。
66714 9
Python3,我把新年祝福写在“雨“中,雨一直下,气氛还算融洽...
|
存储 程序员 Python
使用Python实现自动生日祝福
使用Python实现自动生日祝福
236 0
使用Python实现自动生日祝福
|
Python
最长情的告白就是陪伴【Python七夕祝福】——那些浪漫的开始
最长情的告白就是陪伴【Python七夕祝福】——那些浪漫的开始
132 0
最长情的告白就是陪伴【Python七夕祝福】——那些浪漫的开始
|
程序员 Python
群答疑随手记:Python turtle绘图实例-----直男程序猿祝福生日快乐
群答疑随手记:Python turtle绘图实例-----直男程序猿祝福生日快乐
群答疑随手记:Python turtle绘图实例-----直男程序猿祝福生日快乐
|
Python
实战!用 Python 给母亲送祝福!
今天是母亲节,小阿酱在这里祝天下所有的母亲节日快乐,作为女儿的我除了买礼物送惊喜外还要用 Python 送上特殊的祝福! 母亲节(Mother’s Day),是一个感谢母亲的节日。妈妈曾经也是一个女孩子,怕黑怕虫子,也会掉眼泪,笨手笨脚怕扎针,但她温柔了我,温柔了岁月。 借此祝全天下妈妈母亲节快乐!
404 0
实战!用 Python 给母亲送祝福!