告别取模软件!用Python脚本批量生成STM32墨水屏天气时钟的图标字库
告别取模软件!用Python脚本批量生成STM32墨水屏天气时钟的图标字库
在嵌入式开发中,墨水屏因其低功耗和类纸显示效果,成为天气时钟等项目的热门选择。然而,传统取模软件的手动操作流程繁琐,尤其当项目需要大量天气图标(如晴、雨、雪等)和固定文字时,重复劳动成为效率瓶颈。本文将介绍如何用Python脚本实现全自动图标处理和字库生成,彻底摆脱手动取模的困扰。
1. 为什么需要自动化字库生成?
传统取模流程存在三大痛点:
- 重复操作:每个图标需单独导入、设置参数、生成代码
- 一致性风险:手动操作易导致尺寸或格式不统一
- 维护困难:图标更新时需要重新走完整流程
通过Python脚本自动化,可实现:
- 批量处理文件夹内所有图标文件
- 统一输出格式和尺寸
- 直接生成可嵌入项目的C语言数组代码
- 建立可复用的开发流程
2. 环境准备与核心工具
2.1 基础环境配置
# 安装必要的Python库 pip install pillow numpy核心工具说明:
- Pillow(PIL):图像处理核心库,支持格式转换和像素操作
- NumPy:优化数组处理效率(可选但推荐)
2.2 项目目录结构建议
weather_clock/ ├── icons/ # 原始图标存放目录 │ ├── sunny.png │ ├── rainy.png │ └── ... ├── output/ # 生成文件输出目录 │ ├── bitmaps/ # 转换后的BMP文件 │ └── font_lib/ # C语言字库代码 └── generate_fonts.py # 主处理脚本3. 核心脚本实现详解
3.1 图像预处理模块
from PIL import Image def preprocess_image(input_path, output_size=(40, 40)): """统一图像尺寸和格式""" img = Image.open(input_path) # 转换为灰度图(墨水屏通常只需单色) img = img.convert('L') # 调整尺寸并应用高质量抗锯齿 img = img.resize(output_size, Image.LANCZOS) return img提示:墨水屏项目通常使用1-bit位图,但先保留灰度信息便于后续灵活处理
3.2 位图转C数组的关键算法
def image_to_hex_array(img, threshold=128): """将图像转换为16进制数组""" width, height = img.size pixels = list(img.getdata()) hex_lines = [] for y in range(height): line_bytes = [] for x in range(width): # 二值化处理 bit = 1 if pixels[y * width + x] < threshold else 0 line_bytes.append(bit) # 每8位组合为一个字节 hex_str = '' for i in range(0, len(line_bytes), 8): byte = line_bytes[i:i+8] byte_value = sum(bit << (7 - pos) for pos, bit in enumerate(byte)) hex_str += f'0x{byte_value:02X},' hex_lines.append(hex_str) return hex_lines3.3 完整批处理流程实现
import os from datetime import datetime def batch_convert_icons(input_dir, output_dir): """批量处理目录中的所有图标""" if not os.path.exists(output_dir): os.makedirs(output_dir) c_code = f"// Auto-generated at {datetime.now()}\n" c_code += "#ifndef WEATHER_ICONS_H\n#define WEATHER_ICONS_H\n\n" for filename in os.listdir(input_dir): if filename.lower().endswith(('.png', '.jpg', '.jpeg')): icon_name = os.path.splitext(filename)[0] img = preprocess_image(os.path.join(input_dir, filename)) # 保存处理后的BMP bmp_path = os.path.join(output_dir, f"{icon_name}.bmp") img.save(bmp_path) # 生成C代码 hex_data = image_to_hex_array(img) c_code += f"// {icon_name} 40x40\n" c_code += f"const unsigned char {icon_name}[] = {{\n" for line in hex_data: c_code += f" {line}\n" c_code += "};\n\n" c_code += "#endif // WEATHER_ICONS_H" # 保存头文件 with open(os.path.join(output_dir, "weather_icons.h"), "w") as f: f.write(c_code)4. 高级优化技巧
4.1 内存优化方案
对于资源受限的STM32设备,可采用以下优化策略:
- 位压缩存储:
// 使用位域结构体节省空间 typedef struct { uint8_t data[200]; // 40x40/8 } WeatherIcon; const WeatherIcon PROGMEM icons[] = { {.data = {0x00, 0x1F, ...}}, // sunny {.data = {0x3C, 0x42, ...}} // rainy };- 动态加载机制:
# 生成分块加载代码 def generate_chunked_code(hex_data, chunk_size=512): chunks = [hex_data[i:i+chunk_size] for i in range(0, len(hex_data), chunk_size)] return [f"const uint8_t chunk_{i}[] = {{ {','.join(chunk)} }};" for i, chunk in enumerate(chunks)]4.2 多分辨率适配方案
通过配置文件支持不同尺寸输出:
# config.yaml icon_sizes: small: 24x24 medium: 40x40 large: 64x64 output_formats: - bmp - c_array处理脚本自动读取配置并生成多套资源:
import yaml with open('config.yaml') as f: config = yaml.safe_load(f) for size_name, dimensions in config['icon_sizes'].items(): width, height = map(int, dimensions.split('x')) batch_convert_icons('icons', f'output/{size_name}', (width, height))5. 工程集成实践
5.1 Makefile自动化集成
.PHONY: generate_fonts generate_fonts: python generate_fonts.py build: generate_fonts arm-none-eabi-gcc -c main.c -o main.o arm-none-eabi-gcc -c display.c -o display.o arm-none-eabi-gcc -o firmware.elf main.o display.o5.2 版本控制策略
建议将生成代码与源文件分离管理:
.gitignore */output/bitmaps/ !*/output/font_lib/weather_icons.h注意:只跟踪最终头文件,中间生成的位图不应纳入版本控制
实际项目中,这套自动化流程将开发效率提升了3-5倍。特别是在需要频繁更新天气图标的场景下,只需替换icons目录中的文件,重新运行脚本即可获得更新后的字库,完全避免了传统方式中枯燥的重复操作。
