50

用Python写一份独特的元宵节祝福

 5 years ago
source link: https://segmentfault.com/a/1190000018205156?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

今天是正月十五,首先 祝大家元宵节快乐!

以前加过我个人微信号的朋友,可以在朋友圈看到我今天发的元宵节祝福图片:

FVFfIvZ.jpg!web

这个祝福文字乍一看其貌不扬,不过点开大图有惊喜:是拿自己 微信好友的头像拼成的

这是通过 python 编程生成的。怎么样,要不要来试下呢?

涉及的原理并不复杂,接下来我们一步步来说明。

首先是 点阵字 的概念:点阵字体是把每一个字符都分成 n * n 个点,然后用每个点的虚实来表示字符的轮廓。点阵字体也叫位图字体,其中每个字形都以一组二维像素信息表示。

汉字那么多,总不能每个字都去自己设计点阵吧?别担心,有现成的点阵字库可以直接使用: HZK16字库 。HZK即汉字库的首字母缩写,HZK16字库是符合GB2312标准的16×16点阵字库,支持的汉字有 6763 个(但可惜不支持英文和数字),每个汉字模型需要16×16一共需要 256 个点来显示。

这样思路就出来了:我们自己输入汉字,根据字符串中汉字字符编码,去HZK16字库中获取点阵信息,拿到信息后根据16*16点阵每个点的数据,print 出不同字符。

Talk is cheap, show me the code

#初始化16*16的点阵位置,每个汉字需要16*16=256个点来表示
rect_list = [] * 16
for i in range(16):
    rect_list.append([] * 16)
#拿“赞”字来演示
text = "赞"
#获取中文的编码
gb2312 = text.encode('gb2312')
hex_str = binascii.b2a_hex(gb2312)
result = str(hex_str, encoding='utf-8')
#根据编码计算“赞”在汉字库中的位置
area = eval('0x' + result[:2]) - 0xA0
index = eval('0x' + result[2:]) - 0xA0
offset = (94 * (area-1) + (index-1)) * 32
font_rect = None
#读取HZK16汉字库文件中“赞”字数据
with open("HZK16", "rb") as f:
    f.seek(offset)
    font_rect = f.read(32)
#根据读取到HZK中数据给我们的16*16点阵赋值
for k in range(len(font_rect) // 2):
    row_list = rect_list[k]
    for j in range(2):
        for i in range(8):
            asc = font_rect[k * 2 + j]
            flag = asc & KEYS[i]
            row_list.append(flag)
#根据获取到的16*16点阵信息,打印到控制台
for row in rect_list:
    for i in row:
        if i:
            #前景字符(即用来表示汉字笔画的输出字符)
            print('0', end=' ')
        else:
            #背景字符(即用来表示背景的输出字符)
            print('.', end=' ')
    print()

解决了输出字符的问题,接下来就考虑,如何把这些点换成微信好友头像呢?

我们通过 itchat 这个开源的微信个人号接口来获取微信好友头像图片。这个在之前的文章《 Crossin:用Python写个了红包提醒,再不怕错过一个亿了 》也使用过。

#通过二维码登录微信网页版
itchat.auto_login()
#获取微信好友信息列表
friendList = itchat.get_friends(update=True)
#读取好友头像
for friend in friendList:
    friend['head_img'] = itchat.get_head_img(userName=friend['UserName'])
    friend['head_img_name'] = "%s.jpg" % friend['UserName']
    #写入文件
    with open(friend['head_img_name'],'wb') as f:
        f.write(friend['head_img'])

有了头像之后,我们通过 PIL (Python Image Library,python的第三方图像处理库) 根据汉字点阵信息拼接头像图片。核心代码片段:

#新建画布,16*16点阵,每个图片边长100
canvas = Image.new('RGB', (1600, 1600), '#FFFFFF')
n = 0
for i in range(16*16):
    #点阵信息为1,即代表此处要显示头像来组字
    if item[i] == "1":
        # 打开图片
        img = Image.open(imgList[n])
        # 缩小图片
        img = img.resize((100, 100), Image.ANTIALIAS)
        # 拼接图片
        canvas.paste(img, ((i % 16) * 100, (i // 16) * 100))
        n += 1

综合以上三个步骤,即可用微信好友头像组成你想要的文字了。

如果你嫌弃这 16x16 的字库效果,也可以通过对图片进行二值化处理,以获取更精致的点阵信息来成字符图。比如这个“福”字,其点阵信息就是我对福字图片处理得到的,最终展示的效果也更美观大方:

iyUjUff.jpg!web

我们也可以利用歌词或视频字幕文件中的时间信息,通过 sleep 控制停顿,实现一个动态展示字幕的功能:

2uueIfQ.jpg!web

更多玩法欢迎你来一起动手挖掘!

篇幅有限,上述仅为部分核心代码的演示。获取完整代码以及可直接使用的 exe 文件,可在公众号( Crossin的编程教室 )里回复关键字 元宵节

----

本文是我们编程教室新春征稿活动的一篇投稿,来自 @TED 同学,如果你经常上我们的论坛,一定见过这个ID的身影,他经常在上面回答其他同学的问题。他自己也开了一个python学习的公众号: TEDxPY ,他的知乎专栏:

myMZ3aF.jpg!web

欢迎各位去找他交流学习。

关于点阵字,他连续写了好几篇文章。更详细的分析和代码,可以戳链接直达,均提供代码下载。

今天我们本次征稿活动( 编程教室2019新春征稿活动 )即将截止,但我们编程教室会持续向所有人开放,如果有投稿或参与志愿者的意向,欢迎随时在公众号里给我们留言。

════


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK