用Python寫一份獨特的元宵節祝福

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

以前加過我個人微信號的朋友,可以在朋友圈看到我今天發的元宵節祝福圖片:

這個祝福文字乍一看其貌不揚,不過點開大圖有驚喜:是拿自己 微信好友的頭像拼成的

這是通過 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 的字庫效果,也可以通過對圖片進行二值化處理,以獲取更精緻的點陣信息來成字符圖。比如這個“福”字,其點陣信息就是我對福字圖片處理得到的,最終展示的效果也更美觀大方:

我們也可以利用歌詞或視頻字幕文件中的時間信息,通過 sleep 控制停頓,實現一個動態展示字幕的功能:

更多玩法歡迎你來一起動手挖掘!

篇幅有限,上述僅爲部分核心代碼的演示。獲取完整代碼以及可直接使用的 exe 文件,可在公衆號( Crossin的編程教室 )裏回覆關鍵字 元宵節

----

本文是我們編程教室新春徵稿活動的一篇投稿,來自 @TED 同學,如果你經常上我們的論壇,一定見過這個ID的身影,他經常在上面回答其他同學的問題。他自己也開了一個python學習的公衆號: TEDxPY ,他的知乎專欄:

TED的Python小寶庫zhuanlan.zhihu.com圖標

歡迎各位去找他交流學習。

關於點陣字,他連續寫了好幾篇文章。更詳細的分析和代碼,可以戳鏈接直達,均提供代碼下載。

今天我們本次徵稿活動(編程教室2019新春徵稿活動)即將截止,但我們編程教室會持續向所有人開放,如果有投稿或參與志願者的意向,歡迎隨時在公衆號裏給我們留言。

════

其他文章及回答:

如何自學Python | 新手引導 | 一圖學Python | 智能防擋彈幕 | 紅包提醒 | 流浪地球

歡迎搜索及關注: Crossin的編程教室

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章