溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

python?HZK16字庫(kù)如何使用

發(fā)布時(shí)間:2023-02-22 10:30:21 來源:億速云 閱讀:116 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“python HZK16字庫(kù)如何使用”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

簡(jiǎn)介

偶然在網(wǎng)上看到熱心網(wǎng)友使用python講微信頭像進(jìn)行了組字,感覺很有意思,就做下研究。

感謝,原文參考自: Python玩微信頭像組字

需求的相關(guān)工具:

python第三方庫(kù)image

pip install image      # 圖像處理

HZK16字庫(kù)的下載

自行百度下載吧,由于網(wǎng)盤鏈接失效暫不給大家分享了。

本應(yīng)該要安裝python的第三方庫(kù)itchat

pip install itchat     # 開源的微信個(gè)人接口

# 騰訊在2019年7月份關(guān)閉了網(wǎng)頁(yè)版登錄接口
# itchat的相關(guān)接口已經(jīng)不能夠正常使用了,原有使用的主要接口有:

# 自動(dòng)登錄微信網(wǎng)頁(yè),會(huì)生成一個(gè)二維碼圖片,手機(jī)掃碼即可登入
itchat.auto_login()
# 獲取微信好友信息列表,從而獲取頭像信息
friendList = itchat.get_friends(update=True)

實(shí)現(xiàn)的原理:

通過itchat獲取微信好友頭像圖片,將設(shè)定的文字按照HZK16字庫(kù)轉(zhuǎn)換為矩陣信息,然后在每個(gè)矩陣點(diǎn)上放置2X2張圖片,最后通過Image生成出來。

雖然itchat不可使用了,但是我們可以使用本地的圖片進(jìn)行模擬效果.

HZK16簡(jiǎn)介

它是符合GB2312國(guó)家標(biāo)準(zhǔn)的16×16點(diǎn)陣字庫(kù),每個(gè)漢字需要**256(16×16)**個(gè)點(diǎn)組成。

其GB2312-80支持的漢字有6763個(gè),符號(hào)682個(gè);其中一級(jí)漢字有 3755個(gè),按聲序排列,二級(jí)漢字有3008個(gè),按偏旁部首排列。

通常情況下中文漢字,在UTF-8格式下占用字節(jié)為2個(gè);在GBK,GB2312格式下占用字節(jié)3個(gè)。因此GB2312的HZK16下的中文漢字占用2個(gè)字節(jié)。其編碼范圍:0xA1A1~0xFEFE,A1-A9為符號(hào)區(qū),B0-F7為漢字區(qū)。

前面說到GB2312格式下漢字占2個(gè)字節(jié),前一個(gè)字節(jié)為該漢字的區(qū)號(hào),每個(gè)區(qū)中記錄94個(gè)漢字;后一個(gè)字節(jié)為該字的位號(hào)。用于記錄漢字在該區(qū)中的位置。

因此要找到一個(gè)漢字在HZK16字庫(kù)中的位置就必須得到它的區(qū)碼和位碼。

  • 區(qū)碼:漢字的第一個(gè)字節(jié) - 0xA0,因?yàn)闈h字編碼是從0xA0區(qū)開始的,所以文件最前面就是從0xA0區(qū)開始,要算出相對(duì)區(qū)碼

  • 位碼:漢字的第二個(gè)字節(jié) - 0xA0

通過區(qū)碼和位碼我們就可以得到漢字在HZK16中的絕對(duì)偏移位置:

'''
* 區(qū)碼或者位碼減1,是由于數(shù)組從0開始,而區(qū)號(hào)位號(hào)是以1開始
* (94*(區(qū)號(hào)-1)+位號(hào)-1)是一個(gè)漢字字模占用的字節(jié)數(shù)
* 乘以32是因?yàn)橐粋€(gè)漢字由32個(gè)字節(jié)存儲(chǔ)(16*16/8)
'''
offset = (94*(區(qū)碼-1)+(位碼-1))*32

案例:

下載HZK16文件后,放置到指定的目錄中,其目錄結(jié)構(gòu)為:

python?HZK16字庫(kù)如何使用

res中放置著一張75X75的png圖片,可放置多個(gè)。代碼為:

# -*- coding:UTF-8 -*-
#!/usr/bin/env python

import os
import math
import binascii
from PIL import Image

# 用于解決錯(cuò)誤:UnicodeEncodeError: 'ascii' codec encode characters in position...
# 原因在于調(diào)用ascii編碼處理字符流時(shí),若字符流不屬于ascii范圍內(nèi)就會(huì)報(bào)錯(cuò)
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

# 每張頭像裁剪后尺寸,建議圖片不要太大,最好寬高一致
HEAD_CLIPSIZE = 75

# 每行列頭像數(shù)目,即每點(diǎn):2*2,可修改為3,即3*3
HEAD_NUM = 2
RECT_WIDTH = 16                                         # 矩陣點(diǎn)寬度 16             
RECT_HEIGHT = 16                                        # 矩陣點(diǎn)高度 16
BYTE_COUNT_PER_FONT = 2*RECT_HEIGHT                     # 占用字節(jié) 32

# 將文字轉(zhuǎn)換為點(diǎn)陣
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點(diǎn)陣位置
        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)
        # 獲取漢字第一個(gè)字節(jié),區(qū)碼
        area = eval('0x' + result[:2]) - 0xA0       
        # 獲取漢字第二個(gè)字節(jié),位碼    
        index = eval('0x' + result[2:]) - 0xA0
        # 獲取漢字在字庫(kù)中的絕對(duì)偏移值
        offset = (94 * (area-1) + (index-1)) * BYTE_COUNT_PER_FONT

        font_rect = None
        # 讀取HZK16字庫(kù)文件
        with open("HZK16", "rb") as f:
            # 獲取目標(biāo)漢字偏移位置
            f.seek(offset)
            # 從數(shù)據(jù)中讀取32字節(jié)數(shù)據(jù)
            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))

    # 圖片數(shù)目
    imgCount = len(imgList)

    #變量n用于循環(huán)遍歷頭像圖片,即當(dāng)所需圖片大于頭像總數(shù)時(shí),循環(huán)使用頭像圖片
    n = 0

    for item in outlist:
        # 創(chuàng)建新圖片
        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):
            #點(diǎn)陣信息為1,即代表此處要顯示頭像來組字
            if item[i] != '1':
                continue 

            # 每個(gè)點(diǎn)使用放置幾個(gè)矩陣,比如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))

            #調(diào)整n以讀取后續(xù)圖片
            n = (n+4) % imgCount

        # 保存圖片 quality代表圖片質(zhì)量,1-100
        canvas.save('result_{0}.jpg'.format(index), quality=100)

# 將gbk轉(zhuǎn)換為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'請(qǐng)輸入您想要生成的文字(ENTER結(jié)束):'
    # 輸入內(nèi)容,將中文從unicode轉(zhuǎn)換為gbk,防止亂碼
    content = raw_input(inputStr.encode('gbk'))
    # 將gbk轉(zhuǎn)換為unicode,以方便遍歷時(shí)能夠遍歷每個(gè)文字或字母
    content = transGbk2Unicode(content)

    print(u'注意:指定文字每個(gè)僅能生成一個(gè)')
    # 循環(huán)遍歷
    index = 0
    for _str in content:
        print(u'生成漢字:' + _str)

        #將字轉(zhuǎn)化為漢字庫(kù)的點(diǎn)陣數(shù)據(jù)
        outlist = char2bit(_str)

        #將頭像圖片按點(diǎn)陣拼接成單字圖片                           
        head2char(index, outlist)
        index += 1

    print(u'生成成功!!!')

執(zhí)行結(jié)果:

python?HZK16字庫(kù)如何使用

python?HZK16字庫(kù)如何使用

“python HZK16字庫(kù)如何使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI