[作品] 为点帧屏做自动取字符模的python脚本

IC爬虫   2022-1-25 21:05 楼主

        前段时间DIY了一款128X32的OLED扩展版模块,非常喜欢这种迷你的屏幕,晚点时间会将这个模块的硬件电路开源给大家。为了适配这个屏需要一款字符取模软件,因为现在我的开发工作都是在Ubuntu的电脑,很多基于windows 的取模软件并不适合我,另外我觉得取个模并且输出特定格式的头文件用python 就可以简单实现,而且自己能控制的代码也方便后续加入想要的功能、输出自己喜欢格式的字符头文件。我先在网上找个到了我可以借鉴的代码,稍加改进就可以用了,非常简单,现在我就给大家讲讲这个代码如何使用。

1、首先推荐一个有非常不错,并且适合点阵屏显示的字符字体网站:https://fontsfree.net/bitmicro01-font-download.html

2、方便大家快速找到各种适合低像素的字体文件,可以点击网站上Bitmap这个分类,如下图:

 

 

3、你就可以找到如下图所示的各种有趣并且占用像素少的字体:

 

4、运行创建字符取模脚本需要的python环境:

 

        a、需要使用python3 ;

        b、使用pip安装依赖库:pip3 install jinja2;

5、取模脚本如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys, os
from PIL import Image, ImageFont, ImageDraw
import argparse
import jinja2
import re
import time

def gen_char(index, c, im):
    bw = (im.size[0] + 7) // 8
    res = {
        'index': index,
        'code': c,
        'offset': bw * im.size[1] * index,
        'rows': []
    }
    
    data = tuple(im.getdata())    
    for row in range(im.size[1]):
        r = {
            'data': [],
            'asc': [],
        }
        for b in range(bw):
            byte = 0
            for i in range(8):
                idx = b * 8 + i
                bit = data[row * im.size[0] + idx] if idx < im.size[0] else 0
                if bit:
                    byte |= 1
                    r['asc'].append('#')
                else:
                    r['asc'].append('.')
                byte <<= 1
            r['data'].append(byte >> 1)
            
        r['asc'] = ''.join(r['asc'])
        res['rows'].append(r)
    return res
        

def main(args):
    fnt = ImageFont.truetype(args.font,size=7)  #打开预设的字体文件,并且设置所用的字体大小
    size = fnt.getsize('A')                     #获取一个字符的size:(cols,rows)
    print (size)
    im = Image.new('RGB', size)                 #创建一张RGB的图片,图片大小就是之前获取的单个字符的所占的像素大小
    draw = ImageDraw.Draw(im)
    
    if args.last - args.first < 1:              #判断需要转码的字符的index 是否出错
        raise ValueError('Invalid --first or --last')
    
    chars = []
    for idx in range(args.last - args.first + 1):                       #遍历需要转码的所有的字符
        draw.rectangle(((0, 0), size), fill = 0)                        #将图片画布清零
        draw.text((0, 0), chr(idx + args.first), font=fnt)              #在画布上按位图绘制指定字符
        chars.append(gen_char(idx, idx + args.first, im.convert('1')))  #convert('1')转为二值图,黑为0,白为255;对字符取模,并装入chars数组中
        
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(os.path.abspath(__file__))), finalize=lambda x: '' if x is None else x)
    print(env.get_template(args.template).render({
        'font': {
            'name': args.name,
            'size': size,
            'charset': args.charset,
            'first': args.first,
            'last': args.last,
        },
        'chars': chars,
        'created': time.ctime()
    }))
    

_CLEAN_RE = re.compile(r'[^a-z0-9_]', re.I)

def clean_str(s):
    return _CLEAN_RE.sub('_', s)

if __name__ == "__main__":
    parser=argparse.ArgumentParser(description='Fixed fonts converter')
    parser.add_argument('-f', '--font', type=str, required=True, help='PIL font filename')
    parser.add_argument('-n', '--name', type=clean_str, required=True, help='Font name')
    parser.add_argument('-c', '--charset', type=clean_str, required=True, help='Charset')
    parser.add_argument('--first', type=int, help='First character', default=1)
    parser.add_argument('--last', type=int, help='Last character', default=255)
    parser.add_argument('-t', '--template', type=str, help='Template filename', default='template.c')
    main(parser.parse_args(sys.argv[1:]))

6、执行取模脚本:python ./create_font_new.py -f ./FontsFree-Net-PIXIES__.ttf -n pixie -c PPP --first 32 --last 127

   

提示词:如果您需要查看本帖隐藏内容,请登录或者注册

回复评论 (3)

谢谢分享:)

加油!在电子行业默默贡献自己的力量!:)
点赞  2022-1-26 11:49

楼主给的网站很好,需要字体的可以看看去。

点赞  2022-1-26 22:29
牛啊牛啊
点赞  2022-2-17 15:22
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复