python HZK16字库使用

您所在的位置:网站首页 汉字库文件是用来解决 python HZK16字库使用

python HZK16字库使用

2023-08-27 22:55| 来源: 网络整理| 查看: 265

环境:

windows7, python2.7 

 

简介:

偶然在网上看到微信头像组字(https://blog.csdn.net/weixin_40796925/article/details/86696016)

其实现原理:通过itchat获取微信好友头像图片,将设定的文字按照HZK16字库转换为矩阵信息,然后在每个矩阵点上放置2*2张图片,最后通过Image生成出来。

1. 安装python第三方库:

pip install itchat # 开源的微信个人接口 pip install image # 图像处理

2. HZK16下载:https://pan.baidu.com/s/1XTBXSeKY3jAH1N7KxAYhRg 提取码:wjt0

运行Demo中发现:

# 自动登录微信网页,会生成一个二维码图片,手机扫码即可登入 # 腾讯在2019年7月份关闭了网页版登录接口,使得无法登录更别提获取微信好友头像图片了 itchat.auto_login() # 获取微信好友信息列表,从而获取头像信息 friendList = itchat.get_friends(update=True)

既然无法通过itchat获取微信头像图片相关,我们可以通过其它现有的图片使用HZK16字库来实现组字效果。

 

HZK16简介

它是符合GB2312国家标准的16×16点阵字库,每个汉字需要256(16×16)个点组成。

其GB2312-80支持的汉字有6763个,符号682个;其中一级汉字有 3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。

通常情况下中文汉字,在UTF-8格式下占用字节为2个;在GBK,GB2312格式下占用字节3个。因此GB2312的HZK16下的中文汉字占用2个字节。其编码范围:0xA1A1~0xFEFE,A1-A9为符号区,B0-F7为汉字区。

前面说到GB2312格式下汉字占2个字节,前一个字节为该汉字的区号,每个区中记录94个汉字;后一个字节为该字的位号。用于记录汉字在该区中的位置。

因此要找到一个汉字在HZK16字库中的位置就必须得到它的区码和位码。

区码:汉字的第一个字节 - 0xA0,因为汉字编码是从0xA0区开始的,所以文件最前面就是从0xA0区开始,要算出相对区码 位码:汉字的第二个字节 - 0xA0

通过区码和位码我们就可以得到汉字在HZK16中的绝对偏移位置:

''' * 区码或者位码减1,是由于数组从0开始,而区号位号是以1开始 * (94*(区号-1)+位号-1)是一个汉字字模占用的字节数 * 乘以32是因为一个汉字由32个字节存储(16*16/8) ''' offset = (94*(区码-1)+(位码-1))*32

 

案例:

下载HZK16文件后,放置到指定的目录中,其目录结构为:

 res中放置着一张75*75的png图片,可放置多个。代码为:

# -*- coding:UTF-8 -*- #!/usr/bin/env python import os import math import binascii from PIL import Image # 用于解决错误:UnicodeEncodeError: 'ascii' codec encode characters in position... # 原因在于调用ascii编码处理字符流时,若字符流不属于ascii范围内就会报错 import sys reload(sys) sys.setdefaultencoding('utf-8') # 每张头像裁剪后尺寸,建议图片不要太大,最好宽高一致 HEAD_CLIPSIZE = 75 # 每行列头像数目,即每点:2*2,可修改为3,即3*3 HEAD_NUM = 2 RECT_WIDTH = 16 # 矩阵点宽度 16 RECT_HEIGHT = 16 # 矩阵点高度 16 BYTE_COUNT_PER_FONT = 2*RECT_HEIGHT # 占用字节 32 # 将文字转换为点阵 def char2bit(textStr): KEYS = [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01] target = [] global count count = 0 # 遍历文字 for x in range(len(textStr)): text = textStr[x] # 初始化16*16点阵位置 rect_list = [] * RECT_WIDTH for i in range(RECT_HEIGHT): rect_list.append([] * RECT_WIDTH) # 获取GB2312编码字符 gb2312 = text.encode('gb2312') hex_str = binascii.b2a_hex(gb2312) result = str(hex_str) # 获取汉字第一个字节,区码 area = eval('0x' + result[:2]) - 0xA0 # 获取汉字第二个字节,位码 index = eval('0x' + result[2:]) - 0xA0 # 获取汉字在字库中的绝对偏移值 offset = (94 * (area-1) + (index-1)) * BYTE_COUNT_PER_FONT font_rect = None # 读取HZK16字库文件 with open("HZK16", "rb") as f: # 获取目标汉字偏移位置 f.seek(offset) # 从数据中读取32字节数据 font_rect = f.read(BYTE_COUNT_PER_FONT) for k in range(len(font_rect)/2): row_list = rect_list[k] for j in range(2): for i in range(8): asc = binascii.b2a_hex(font_rect[k * 2 + j]) asc = asc = eval('0x' + asc) flag = asc & KEYS[i] row_list.append(flag) output = [] _str = '' for row in rect_list: for i in row: if i: output.append('1') _str += '0' count+=1 else: output.append('0') _str += '.' print(_str) _str = '' target.append(''.join(output)) return target def head2char(index, outlist): # 获取资源列表 imgList = [] workspace = os.getcwd() respath = os.path.join(workspace, 'res') for root, dirs, files in os.walk(respath): for filename in files: imgList.append(os.path.join(root, filename)) # 图片数目 imgCount = len(imgList) #变量n用于循环遍历头像图片,即当所需图片大于头像总数时,循环使用头像图片 n = 0 for item in outlist: # 创建新图片 canvasWidth = RECT_WIDTH * HEAD_NUM * HEAD_CLIPSIZE canvasHeight = RECT_HEIGHT * HEAD_NUM * HEAD_CLIPSIZE canvas = Image.new('RGB', (canvasWidth, canvasHeight), '#E0EEE0') # 遍历 RECT_WIDTH * RECT_HEIGHT 矩阵 for i in range(RECT_WIDTH * RECT_HEIGHT): #点阵信息为1,即代表此处要显示头像来组字 if item[i] != '1': continue # 每个点使用放置几个矩阵,比如2*2,3*3 for count in range(pow(HEAD_NUM, 2)): # 获取图片索引 imgIndex = (n + count) % imgCount # 读取图片 headImg = Image.open(imgList[imgIndex]) # 重置图片大小 headImg = headImg.resize((HEAD_CLIPSIZE, HEAD_CLIPSIZE), Image.ANTIALIAS) # 拼接图片 posx = ((i % RECT_WIDTH) * HEAD_NUM + (count%HEAD_NUM)) * HEAD_CLIPSIZE posy = ((i // RECT_HEIGHT) * HEAD_NUM + (count//HEAD_NUM)) * HEAD_CLIPSIZE canvas.paste(headImg, (posx, posy)) #调整n以读取后续图片 n = (n+4) % imgCount # 保存图片 quality代表图片质量,1-100 canvas.save('result_{0}.jpg'.format(index), quality=100) # 将gbk转换为unicode格式 def transGbk2Unicode(str_v): str_s = str_v.replace(r'%', r'\x') res = eval(repr(str_s).replace('\\\\', '\\')) return res.decode('gb2312') if __name__=="__main__": inputStr = u'请输入您想要生成的文字(ENTER结束):' # 输入内容,将中文从unicode转换为gbk,防止乱码 content = raw_input(inputStr.encode('gbk')) # 将gbk转换为unicode,以方便遍历时能够遍历每个文字或字母 content = transGbk2Unicode(content) print(u'注意:指定文字每个仅能生成一个') # 循环遍历 index = 0 for _str in content: print(u'生成汉字:' + _str) #将字转化为汉字库的点阵数据 outlist = char2bit(_str) #将头像图片按点阵拼接成单字图片 head2char(index, outlist) index += 1 print(u'生成成功!!!')

执行结果:

 

 拓展:

若想将python打包生成exe,可参考:https://www.cnblogs.com/SkyflyBird/p/11844304.html

 

 参考:

HZK16的原理:https://blog.twofei.com/embedded/hzk.html

python微信头像组字:https://blog.csdn.net/weixin_40796925/article/details/86696016

python实现点阵字体读取与转换:https://www.jb51.net/article/155543.htm



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3